HORIZON HASKELLDocslts/ghc-9.10.x248f8f02026-10-05Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · 248f8f0 · 2026-10-05

Modulesome-1.0.6Haskell2010

Data.GADT.Compare

  • 1 type
  • 2 classes
  • 4 values
  • Packagesome-1.0.6
  • Exports7
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourceInternal.hs

Equality

4 declarations
classclass GEq (f :: k -> Type) where
#

A class for type-contexts which contain enough information to (at least in some cases) decide the equality of types occurring within them.

This class is sometimes confused with TestEquality from base. TestEquality only checks type equality.

Consider

Example1 expression
data Tag a where TagInt1 :: Tag Int; TagInt2 :: Tag Int

The correct TestEquality Tag instance is

Example1 expression
:{instance TestEquality Tag where    testEquality TagInt1 TagInt1 = Just Refl    testEquality TagInt1 TagInt2 = Just Refl    testEquality TagInt2 TagInt1 = Just Refl    testEquality TagInt2 TagInt2 = Just Refl:}

While we can define

instance GEq Tag where
   geq = testEquality

this will mean we probably want to have

instance Eq Tag where
   _ == _ = True

Note: In the future version of some package (to be released around GHC-9.6 / 9.8) the forall a. Eq (f a) constraint will be added as a constraint to GEq, with a law relating GEq and Eq:

geq x y = Just Refl   ⇒  x == y = True        ∀ (x :: f a) (y :: f b)
x == y                ≡  isJust (geq x y)     ∀ (x, y :: f a)

So, the more useful GEq Tag instance would differentiate between different constructors:

Example1 expression
:{instance GEq Tag where    geq TagInt1 TagInt1 = Just Refl    geq TagInt1 TagInt2 = Nothing    geq TagInt2 TagInt1 = Nothing    geq TagInt2 TagInt2 = Just Refl:}

which is consistent with a derived Eq instance for Tag

Example1 expression
deriving instance Eq (Tag a)

Note that even if a ~ b, the geq (x :: f a) (y :: f b) may be Nothing (when value terms are inequal).

The consistency of GEq and Eq is easy to check by exhaustion:

Example2 expressions
let checkFwdGEq :: (forall a. Eq (f a), GEq f) => f a -> f b -> Bool; checkFwdGEq x y = case geq x y of Just Refl -> x == y; Nothing -> True(checkFwdGEq TagInt1 TagInt1, checkFwdGEq TagInt1 TagInt2, checkFwdGEq TagInt2 TagInt1, checkFwdGEq TagInt2 TagInt2)(True,True,True,True)
Example2 expressions
let checkBwdGEq :: (Eq (f a), GEq f) => f a -> f a -> Bool; checkBwdGEq x y = if x == y then isJust (geq x y) else isNothing (geq x y)(checkBwdGEq TagInt1 TagInt1, checkBwdGEq TagInt1 TagInt2, checkBwdGEq TagInt2 TagInt1, checkBwdGEq TagInt2 TagInt2)(True,True,True,True)

Methods

  • geq :: f a -> f b -> Maybe (a :~: b)

    Produce a witness of type-equality, if one exists.

    A handy idiom for using this would be to pattern-bind in the Maybe monad, eg.:

    extract :: GEq tag => tag a -> DSum tag -> Maybe a
    extract t1 (t2 :=> x) = do
        Refl <- geq t1 t2
        return x

    Or in a list comprehension:

    extractMany :: GEq tag => tag a -> [DSum tag] -> [a]
    extractMany t1 things = [ x | (t2 :=> x) <- things, Refl <- maybeToList (geq t1 t2)]

    (Making use of the DSum type from Data.Dependent.Sum in both examples)

Instances10GEq, …
  • GEq SCharDefined in some-1.0.6 · Data.GADT.Internal
  • GEq SSymbolDefined in some-1.0.6 · Data.GADT.Internal
  • GEq SNatDefined in some-1.0.6 · Data.GADT.Internal
  • GEq TypeRepDefined in some-1.0.6 · Data.GADT.Internal
  • GEq ((:~:) a)Defined in some-1.0.6 · Data.GADT.Internal
  • GEq ((:~~:) a)Defined in some-1.0.6 · Data.GADT.Internal
  • (GEq a, GEq b) => GEq (Product a b)Defined in some-1.0.6 · Data.GADT.Internal
  • (GEq a, GEq b) => GEq (Sum a b)Defined in some-1.0.6 · Data.GADT.Internal
  • (GEq a, GEq b) => GEq (a :*: b)Defined in some-1.0.6 · Data.GADT.Internal
  • (GEq f, GEq g) => GEq (f :+: g)Defined in some-1.0.6 · Data.GADT.Internal
valuedefaultEq :: GEq f => f a -> f b -> Bool
#

If f has a GEq instance, this function makes a suitable default implementation of (==).

valuedefaultNeq :: GEq f => f a -> f b -> Bool
#

If f has a GEq instance, this function makes a suitable default implementation of (/=).

Total order comparison

3 declarations
classclass GEq f => GCompare (f :: k -> Type) where
#

Type class for comparable GADT-like structures. When 2 things are equal, must return a witness that their parameter types are equal as well (GEQ).

Methods

Instances10GCompare, …
datadata GOrdering (a :: k) (b :: k) where
#

A type for the result of comparing GADT constructors; the type parameters of the GADT values being compared are included so that in the case where they are equal their parameter types can be unified.

Constructors

Instances5GRead, GShow, Eq, Ord, Show