Skip to content

Commit 8d45aaa

Browse files
committed
Add instances for SNat, SSymbol, and SChar
These were introduced to `GHC.TypeNats` and `GHC.TypeLits` in `base-4.18.0.0`. They did not receive `Eq` or `Ord` instances until `base-4.19.0.0`, however, which are required for the superclasses of `EqP` and `OrdP`. To account for this, I introduce a conditional dependency on `base-orphans`, which backports the `Eq` and `Ord` instances to older versions of `base`.
1 parent 78601e4 commit 8d45aaa

File tree

4 files changed

+97
-10
lines changed

4 files changed

+97
-10
lines changed

some.cabal

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ library
7272
base >=4.12 && <4.20
7373
, deepseq >=1.4.4.0 && <1.6
7474

75+
if !impl(ghc >= 9.8)
76+
build-depends:
77+
base-orphans >= 0.9.1 && <0.10
78+
7579
if impl(ghc >=9.0)
7680
-- these flags may abort compilation with GHC-8.10
7781
-- https://gitlab.haskell.org/ghc/ghc/-/merge_requests/3295

src/Data/EqP.hs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ import System.Mem.StableName (StableName, eqStableName)
2020
#if MIN_VERSION_base(4,18,0)
2121
import Data.Functor.Product (Product (..))
2222
import Data.Functor.Sum (Sum (..))
23+
import qualified GHC.TypeLits as TL
24+
import qualified GHC.TypeNats as TN
25+
#endif
26+
27+
#if !MIN_VERSION_base(4,19,0)
28+
import Data.Orphans ()
2329
#endif
2430

2531
import qualified Type.Reflection as TR
@@ -88,6 +94,17 @@ instance (EqP a, EqP b) => EqP (a :*: b) where
8894
instance EqP TR.TypeRep where
8995
eqp x y = TR.SomeTypeRep x == TR.SomeTypeRep y
9096

97+
#if MIN_VERSION_base(4,18,0)
98+
instance EqP TL.SChar where
99+
eqp _ _ = True
100+
101+
instance EqP TL.SSymbol where
102+
eqp _ _ = True
103+
104+
instance EqP TN.SNat where
105+
eqp _ _ = True
106+
#endif
107+
91108
instance EqP Proxy where
92109
eqp _ _ = True
93110

src/Data/GADT/Internal.hs

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ import qualified Type.Reflection as TR
2727
import Data.Kind (Constraint)
2828
#endif
2929

30+
#if MIN_VERSION_base(4,18,0)
31+
import qualified GHC.TypeLits as TL
32+
import qualified GHC.TypeNats as TN
33+
#endif
34+
3035
-- $setup
3136
-- >>> :set -XKindSignatures -XGADTs -XTypeOperators -XStandaloneDeriving -XQuantifiedConstraints
3237
-- >>> import Data.Type.Equality
@@ -68,6 +73,17 @@ instance GShow ((:~~:) a) where
6873
instance GShow TR.TypeRep where
6974
gshowsPrec = showsPrec
7075

76+
#if MIN_VERSION_base(4,18,0)
77+
instance GShow TL.SChar where
78+
gshowsPrec = showsPrec
79+
80+
instance GShow TL.SSymbol where
81+
gshowsPrec = showsPrec
82+
83+
instance GShow TN.SNat where
84+
gshowsPrec = showsPrec
85+
#endif
86+
7187
--
7288
-- | >>> gshow (InL Refl :: Sum ((:~:) Int) ((:~:) Bool) Int)
7389
-- "InL Refl"
@@ -339,6 +355,17 @@ instance (GEq a, GEq b) => GEq (a :*: b) where
339355
instance GEq TR.TypeRep where
340356
geq = testEquality
341357

358+
#if MIN_VERSION_base(4,18,0)
359+
instance GEq TL.SChar where
360+
geq = testEquality
361+
362+
instance GEq TL.SSymbol where
363+
geq = testEquality
364+
365+
instance GEq TN.SNat where
366+
geq = testEquality
367+
#endif
368+
342369
-------------------------------------------------------------------------------
343370
-- GCompare
344371
-------------------------------------------------------------------------------
@@ -426,20 +453,42 @@ instance GCompare ((:~~:) a) where
426453
gcompare HRefl HRefl = GEQ
427454

428455
instance GCompare TR.TypeRep where
429-
gcompare t1 t2 =
430-
case testEquality t1 t2 of
431-
Just Refl -> GEQ
432-
Nothing ->
433-
case compare (TR.SomeTypeRep t1) (TR.SomeTypeRep t2) of
434-
LT -> GLT
435-
GT -> GGT
436-
EQ -> error "impossible: 'testEquality' and 'compare' \
437-
\are inconsistent for TypeRep; report this \
438-
\as a GHC bug"
456+
gcompare = gcompareSing "TypeRep" TR.SomeTypeRep
457+
458+
#if MIN_VERSION_base(4,18,0)
459+
instance GCompare TL.SChar where
460+
gcompare = gcompareSing "SChar" TL.fromSChar
461+
462+
instance GCompare TL.SSymbol where
463+
gcompare = gcompareSing "SSymbol" TL.fromSSymbol
464+
465+
instance GCompare TN.SNat where
466+
gcompare = gcompareSing "SNat" TN.fromSNat
467+
#endif
439468

440469
defaultCompare :: GCompare f => f a -> f b -> Ordering
441470
defaultCompare x y = weakenOrdering (gcompare x y)
442471

472+
-- | An implementation of 'gcompare' for a singleton type.
473+
gcompareSing :: (TestEquality f, Ord c)
474+
=> String
475+
-- ^ The name of the singleton type.
476+
-- (Only used for error message purposes.)
477+
-> (forall x. f x -> c)
478+
-- ^ How to turn the singleton type into a value that can be
479+
-- compared with 'Ord'.
480+
-> f a -> f b -> GOrdering a b
481+
gcompareSing singName toOrd t1 t2 =
482+
case testEquality t1 t2 of
483+
Just Refl -> GEQ
484+
Nothing ->
485+
case compare (toOrd t1) (toOrd t2) of
486+
LT -> GLT
487+
GT -> GGT
488+
EQ -> error $ "impossible: 'testEquality' and 'compare' are inconsistent for "
489+
++ singName
490+
++ "; report this as a GHC bug"
491+
443492
instance (GCompare a, GCompare b) => GCompare (Sum a b) where
444493
gcompare (InL x) (InL y) = gcompare x y
445494
gcompare (InL _) (InR _) = GLT

src/Data/OrdP.hs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ import GHC.Generics ((:*:) (..), (:+:) (..))
2020
#if MIN_VERSION_base(4,18,0)
2121
import Data.Functor.Product (Product (..))
2222
import Data.Functor.Sum (Sum (..))
23+
import qualified GHC.TypeLits as TL
24+
import qualified GHC.TypeNats as TN
25+
#endif
26+
27+
#if !MIN_VERSION_base(4,19,0)
28+
import Data.Orphans ()
2329
#endif
2430

2531
import qualified Type.Reflection as TR
@@ -75,6 +81,17 @@ instance (OrdP a, OrdP b) => OrdP (a :*: b) where
7581
instance OrdP TR.TypeRep where
7682
comparep x y = compare (TR.SomeTypeRep x) (TR.SomeTypeRep y)
7783

84+
#if MIN_VERSION_base(4,18,0)
85+
instance OrdP TL.SChar where
86+
comparep _ _ = EQ
87+
88+
instance OrdP TL.SSymbol where
89+
comparep _ _ = EQ
90+
91+
instance OrdP TN.SNat where
92+
comparep _ _ = EQ
93+
#endif
94+
7895
instance OrdP Proxy where
7996
comparep _ _ = EQ
8097

0 commit comments

Comments
 (0)