syntactic-2.0: extras/TypeUniverseClosed.hs
-- | Typed type reification, type-level reasoning and dynamic types
--
-- This module is meant as a reference for understanding the "Data.Syntactic.TypeUniverse" module.
module TypeUniverseClosed where
import Data.Constraint
-- | Typed representation of types (reification of type @a@)
data TypeRep a
where
BoolType :: TypeRep Bool
IntType :: TypeRep Int
FloatType :: TypeRep Float
ListType :: TypeRep a -> TypeRep [a]
-- | Type reification
class Typeable a
where
-- | Reifies type @a@
typeRep :: TypeRep a
instance Typeable Bool where typeRep = BoolType
instance Typeable Int where typeRep = IntType
instance Typeable Float where typeRep = FloatType
instance Typeable a => Typeable [a] where typeRep = ListType typeRep
typeEq :: TypeRep a -> TypeRep b -> Maybe (Dict (a ~ b))
typeEq BoolType BoolType = Just Dict
typeEq IntType IntType = Just Dict
typeEq FloatType FloatType = Just Dict
typeEq (ListType t1) (ListType t2) = do Dict <- typeEq t1 t2; return Dict
typeEq _ _ = Nothing
hasTypeable :: TypeRep a -> Dict (Typeable a)
hasTypeable BoolType = Dict
hasTypeable IntType = Dict
hasTypeable FloatType = Dict
hasTypeable (ListType t) | Dict <- hasTypeable t = Dict
hasEq :: TypeRep a -> Dict (Eq a)
hasEq BoolType = Dict
hasEq IntType = Dict
hasEq FloatType = Dict
hasEq (ListType t) | Dict <- hasEq t = Dict
hasShow :: TypeRep a -> Dict (Show a)
hasShow BoolType = Dict
hasShow IntType = Dict
hasShow FloatType = Dict
hasShow (ListType t) | Dict <- hasShow t = Dict
hasNum :: TypeRep a -> Maybe (Dict (Num a))
hasNum BoolType = Nothing
hasNum IntType = Just Dict
hasNum FloatType = Just Dict
hasNum (ListType t) = Nothing
-- | Safe cast (does not use @unsafeCoerce@ underneath)
cast :: forall a b . (Typeable a, Typeable b) => a -> Maybe b
cast a = do
Dict <- typeEq (typeRep :: TypeRep a) (typeRep :: TypeRep b)
return a
typeOf :: Typeable a => a -> TypeRep a
typeOf _ = typeRep
data Dynamic
where
Dyn :: TypeRep a -> a -> Dynamic
toDyn :: Typeable a => a -> Dynamic
toDyn = Dyn typeRep
fromDyn :: Typeable a => Dynamic -> Maybe a
fromDyn (Dyn t a) | Dict <- hasTypeable t = cast a
instance Eq Dynamic
where
Dyn ta a == Dyn tb b
| Just Dict <- typeEq ta tb
, Dict <- hasEq ta
= a == b
_ == _ = False
instance Show Dynamic
where
show (Dyn t a) | Dict <- hasShow t = show a