| Safe Haskell | Safe |
|---|---|
| Language | Haskell2010 |
Data.GADT.Internal
Synopsis
- class GShow t where
- gshowsPrec :: Int -> t a -> ShowS
- defaultGshowsPrec :: Show (t a) => Int -> t a -> ShowS
- gshows :: GShow t => t a -> ShowS
- gshow :: GShow t => t a -> String
- type GReadS t = String -> [(Some t, String)]
- getGReadResult :: Some tag -> (forall a. tag a -> b) -> b
- mkGReadResult :: tag a -> Some tag
- class GRead t where
- greadsPrec :: Int -> GReadS t
- greads :: GRead t => GReadS t
- gread :: GRead t => String -> (forall a. t a -> b) -> b
- greadMaybe :: GRead t => String -> (forall a. t a -> b) -> Maybe b
- class GEq f where
- defaultGeq :: GCompare f => f a -> f b -> Maybe (a :~: b)
- defaultEq :: GEq f => f a -> f b -> Bool
- defaultNeq :: GEq f => f a -> f b -> Bool
- data GOrdering a b where
- weakenOrdering :: GOrdering a b -> Ordering
- class GEq f => GCompare f where
- defaultCompare :: GCompare f => f a -> f b -> Ordering
- newtype Some tag = S {
- withSome :: forall r. (forall a. tag a -> r) -> r
- mkSome :: tag a -> Some tag
- mapSome :: (forall x. f x -> g x) -> Some f -> Some g
- foldSome :: (forall a. tag a -> b) -> Some tag -> b
- traverseSome :: Functor m => (forall a. f a -> m (g a)) -> Some f -> m (Some g)
- withSomeM :: Monad m => m (Some tag) -> (forall a. tag a -> m r) -> m r
Documentation
>>>:set -XKindSignatures -XGADTs -XTypeOperators -XStandaloneDeriving -XQuantifiedConstraints>>>import Data.Type.Equality>>>import Data.Functor.Sum>>>import Data.Maybe (isJust, isNothing)>>>import GHC.Generics
Show-like class for 1-type-parameter GADTs. GShow t => ... is equivalent to something
like (forall a. Show (t a)) => .... The easiest way to create instances would probably be
to write (or derive) an instance Show (T a), and then simply say:
instance GShow t where gshowsPrec = defaultGshowsPrec
Methods
gshowsPrec :: Int -> t a -> ShowS Source #
Instances
| GShow (TypeRep :: k -> Type) Source # | |
Defined in Data.GADT.Internal | |
| GShow ((:~:) a :: k -> Type) Source # | |
Defined in Data.GADT.Internal | |
| GShow (GOrdering a :: k -> Type) Source # | |
Defined in Data.GADT.Internal | |
| (GShow a, GShow b) => GShow (Product a b :: k -> Type) Source # |
|
Defined in Data.GADT.Internal | |
| (GShow a, GShow b) => GShow (Sum a b :: k -> Type) Source # |
|
Defined in Data.GADT.Internal | |
| GShow ((:~~:) a :: k -> Type) Source # | Since: 1.0.4 |
Defined in Data.GADT.Internal | |
| (GShow a, GShow b) => GShow (a :*: b :: k -> Type) Source # |
Since: 1.0.4 |
Defined in Data.GADT.Internal | |
| (GShow a, GShow b) => GShow (a :+: b :: k -> Type) Source # |
Since: 1.0.4 |
Defined in Data.GADT.Internal | |
defaultGshowsPrec :: Show (t a) => Int -> t a -> ShowS Source #
If f has a 'Show (f a)' instance, this function makes a suitable default
implementation of gshowsPrec.
Since: 1.0.4
type GReadS t = String -> [(Some t, String)] Source #
GReadS t is equivalent to ReadS (forall b. (forall a. t a -> b) -> b), which is
in turn equivalent to ReadS (Exists t) (with data Exists t where Exists :: t a -> Exists t)
getGReadResult :: Some tag -> (forall a. tag a -> b) -> b Source #
mkGReadResult :: tag a -> Some tag Source #
Read-like class for 1-type-parameter GADTs. Unlike GShow, this one cannot be
mechanically derived from a Read instance because greadsPrec must choose the phantom
type based on the String being parsed.
Methods
greadsPrec :: Int -> GReadS t Source #
Instances
| GRead ((:~:) a :: k -> Type) Source # | |
Defined in Data.GADT.Internal | |
| GRead (GOrdering a :: k -> Type) Source # | |
Defined in Data.GADT.Internal | |
| (GRead a, GRead b) => GRead (Sum a b :: k -> Type) Source # | |
Defined in Data.GADT.Internal | |
| (GRead a, GRead b) => GRead (a :+: b :: k -> Type) Source # | Since: 1.0.4 |
Defined in Data.GADT.Internal | |
| k1 ~ k2 => GRead ((:~~:) a :: k2 -> Type) Source # | Since: 1.0.4 |
Defined in Data.GADT.Internal | |
greadMaybe :: GRead t => String -> (forall a. t a -> b) -> Maybe b Source #
>>>greadMaybe "InL Refl" mkSome :: Maybe (Some (Sum ((:~:) Int) ((:~:) Bool)))Just (mkSome (InL Refl))
>>>greadMaybe "L1 Refl" mkSome :: Maybe (Some ((:~:) Int :+: (:~:) Bool))Just (mkSome (L1 Refl))
>>>greadMaybe "garbage" mkSome :: Maybe (Some ((:~:) Int))Nothing
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
>>>data Tag a where TagInt1 :: Tag Int; TagInt2 :: Tag Int
The correct instance isTestEquality Tag
>>>:{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
instanceGEqTag wheregeq=testEquality
this will mean we probably want to have
instanceEqTag 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:
geqx y = Just Refl ⇒ x == y = True ∀ (x :: f a) (y :: f b) x == y ≡ isJust (geqx y) ∀ (x, y :: f a)
So, the more useful instance would differentiate between
different constructors:GEq Tag
>>>:{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
>>>deriving instance Eq (Tag a)
Note that even if a ~ b, the may
be geq (x :: f a) (y :: f b)Nothing (when value terms are inequal).
The consistency of GEq and Eq is easy to check by exhaustion:
>>>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)
>>>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) Source #
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 xOr 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)
Instances
| GEq (TypeRep :: k -> Type) Source # | |
| GEq ((:~:) a :: k -> Type) Source # | |
| (GEq a, GEq b) => GEq (Product a b :: k -> Type) Source # | |
| (GEq a, GEq b) => GEq (Sum a b :: k -> Type) Source # | |
| GEq ((:~~:) a :: k -> Type) Source # | Since: 1.0.4 |
| (GEq a, GEq b) => GEq (a :*: b :: k -> Type) Source # | Since: 1.0.4 |
| (GEq f, GEq g) => GEq (f :+: g :: k -> Type) Source # | Since: 1.0.4 |
defaultNeq :: GEq f => f a -> f b -> Bool Source #
data GOrdering a b where Source #
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.
Instances
| GRead (GOrdering a :: k -> Type) Source # | |
Defined in Data.GADT.Internal | |
| GShow (GOrdering a :: k -> Type) Source # | |
Defined in Data.GADT.Internal | |
| Show (GOrdering a b) Source # | |
| Eq (GOrdering a b) Source # | |
| Ord (GOrdering a b) Source # | |
Defined in Data.GADT.Internal Methods compare :: GOrdering a b -> GOrdering a b -> Ordering # (<) :: GOrdering a b -> GOrdering a b -> Bool # (<=) :: GOrdering a b -> GOrdering a b -> Bool # (>) :: GOrdering a b -> GOrdering a b -> Bool # (>=) :: GOrdering a b -> GOrdering a b -> Bool # | |
weakenOrdering :: GOrdering a b -> Ordering Source #
TODO: Think of a better name
This operation forgets the phantom types of a GOrdering value.
class GEq f => GCompare f where Source #
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).
Instances
| GCompare (TypeRep :: k -> Type) Source # | |
| GCompare ((:~:) a :: k -> Type) Source # | |
| (GCompare a, GCompare b) => GCompare (Product a b :: k -> Type) Source # | |
| (GCompare a, GCompare b) => GCompare (Sum a b :: k -> Type) Source # | |
| GCompare ((:~~:) a :: k -> Type) Source # | Since: 1.0.4 |
| (GCompare a, GCompare b) => GCompare (a :*: b :: k -> Type) Source # | Since: 1.0.4 |
| (GCompare f, GCompare g) => GCompare (f :+: g :: k -> Type) Source # | Since: 1.0.4 |
defaultCompare :: GCompare f => f a -> f b -> Ordering Source #
Existential. This is type is useful to hide GADTs' parameters.
>>>data Tag :: * -> * where TagInt :: Tag Int; TagBool :: Tag Bool>>>instance GShow Tag where gshowsPrec _ TagInt = showString "TagInt"; gshowsPrec _ TagBool = showString "TagBool">>>classify s = case s of "TagInt" -> [mkGReadResult TagInt]; "TagBool" -> [mkGReadResult TagBool]; _ -> []>>>instance GRead Tag where greadsPrec _ s = [ (r, rest) | (con, rest) <- lex s, r <- classify con ]
With Church-encoding youcan only use a functions:
>>>let y = mkSome TagBool>>>ymkSome TagBool
>>>withSome y $ \y' -> case y' of { TagInt -> "I"; TagBool -> "B" } :: String"B"
or explicitly work with S
>>>let x = S $ \f -> f TagInt>>>xmkSome TagInt
>>>case x of S f -> f $ \x' -> case x' of { TagInt -> "I"; TagBool -> "B" } :: String"I"
The implementation of mapSome is safe.
>>>let f :: Tag a -> Tag a; f TagInt = TagInt; f TagBool = TagBool>>>mapSome f ymkSome TagBool
but you can also use:
>>>withSome y (mkSome . f)mkSome TagBool
>>>read "Some TagBool" :: Some TagmkSome TagBool
>>>read "mkSome TagInt" :: Some TagmkSome TagInt