Skip to content

Commit 2ab4c73

Browse files
authored
Merge pull request #385 from haskell/mpj/comments-and-changelog
Add a few comments and tweaks to dependent-sum replacements
2 parents ad7bc0e + 233ca66 commit 2ab4c73

File tree

2 files changed

+27
-4
lines changed

2 files changed

+27
-4
lines changed

lsp-types/src/Language/LSP/Types/Method.hs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,24 +188,38 @@ data SMethod (m :: Method f t) where
188188
SCancelRequest :: SMethod CancelRequest
189189
SCustomMethod :: Text -> SMethod CustomMethod
190190

191+
-- This instance is written manually rather than derived to avoid a dependency
192+
-- on 'dependent-sum-template'.
191193
instance GEq SMethod where
192194
geq x y = case gcompare x y of
193195
GLT -> Nothing
194196
GEQ -> Just Refl
195197
GGT -> Nothing
196198

199+
-- This instance is written manually rather than derived to avoid a dependency
200+
-- on 'dependent-sum-template'.
197201
instance GCompare SMethod where
198202
gcompare (SCustomMethod x) (SCustomMethod y) = case x `compare` y of
199203
LT -> GLT
200204
EQ -> GEQ
201205
GT -> GGT
206+
-- This is much more compact than matching on every pair of constructors, which
207+
-- is what we would need to do for GHC to 'see' that this is correct. Nonetheless
208+
-- it is safe: since there is only one constructor of 'SMethod' for each 'Method',
209+
-- the argument types can only be equal if the constructor tag is equal.
202210
gcompare x y = case I# (dataToTag# x) `compare` I# (dataToTag# y) of
203211
LT -> GLT
204212
EQ -> unsafeCoerce GEQ
205213
GT -> GGT
206214

207-
deriving instance Eq (SMethod m)
208-
deriving instance Ord (SMethod m)
215+
instance Eq (SMethod m) where
216+
-- This defers to 'GEq', ensuring that this version is compatible.
217+
(==) = defaultEq
218+
219+
instance Ord (SMethod m) where
220+
-- This defers to 'GCompare', ensuring that this version is compatible.
221+
compare = defaultCompare
222+
209223
deriving instance Show (SMethod m)
210224

211225
-- Some useful type synonyms

lsp-types/src/Language/LSP/Types/SMethodMap.hs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,22 @@ import Data.Kind (Type)
2121
import Data.Map (Map)
2222
import qualified Data.Map.Strict as Map
2323
import Data.Text (Text)
24-
import GHC.Exts (Int(..), dataToTag#)
24+
import GHC.Exts (Int(..), dataToTag#, Any)
2525
import Unsafe.Coerce (unsafeCoerce)
2626

2727
import Language.LSP.Types.Method (Method(..), SMethod(..))
2828

29+
-- This type exists to avoid a dependency on 'dependent-map'. It is less
30+
-- safe (since we use 'unsafeCoerce') but much simpler and hence easier to include.
31+
-- | A specialized altenative to a full dependent map for use with 'SMethod'.
2932
data SMethodMap (v :: Method f t -> Type) =
30-
SMethodMap !(IntMap (v 'CustomMethod)) !(Map Text (v 'CustomMethod))
33+
-- This works by using an 'IntMap' indexed by constructor tag for the majority
34+
-- of 'SMethod's, which have no parameters, and hence can only appear once as keys
35+
-- in the map. We do not attempt to be truly dependent here, and instead exploit
36+
-- 'usafeCoerce' to go to and from 'v Any'.
37+
-- The sole exception is 'SCustomMethod', for which we keep a separate map from
38+
-- its 'Text' parameter (and where we can get the type indices right).
39+
SMethodMap !(IntMap (v Any)) !(Map Text (v 'CustomMethod))
3140

3241
toIx :: SMethod a -> Int
3342
toIx k = I# (dataToTag# k)

0 commit comments

Comments
 (0)