packages feed

open-witness-0.6: src/Data/Type/OpenWitness/Typeable.hs

-- | This is an approximate re-implementation of "Data.Typeable" using open witnesses.
module Data.Type.OpenWitness.Typeable where

import Data.Kind
import Data.Type.OpenWitness
import Data.Type.OpenWitness.TypeRep
import Data.Type.Witness
import Prelude

-- | types of kind @Type@ with a representation
class Typeable (a :: k) where
    typeRep :: TypeRep a

instance (Typeable (f :: k1 -> k2), Typeable (a :: k1)) => Typeable (f a) where
    typeRep = ApplyTypeRep typeRep typeRep

instance Typeable Type where
    typeRep = SimpleTypeRep $(iowitness [t|Type|])

type Fun = (->)

instance Typeable (->) where
    typeRep = SimpleTypeRep $(iowitness [t|Fun|])

instance Typeable Constraint where
    typeRep = SimpleTypeRep $(iowitness [t|Constraint|])

instance Typeable TypeRep where
    typeRep = SimpleTypeRep $(iowitness [t|TypeRep|])

instance Typeable Typeable where
    typeRep = SimpleTypeRep $(iowitness [t|Typeable|])

instance Typeable () where
    typeRep = SimpleTypeRep $(iowitness [t|()|])

instance Typeable (,) where
    typeRep = SimpleTypeRep $(iowitness [t|(,)|])

instance Typeable Either where
    typeRep = SimpleTypeRep $(iowitness [t|Either|])

instance Typeable Maybe where
    typeRep = SimpleTypeRep $(iowitness [t|Maybe|])

instance Typeable [] where
    typeRep = SimpleTypeRep $(iowitness [t|[]|])

instance Typeable Bool where
    typeRep = SimpleTypeRep $(iowitness [t|Bool|])

instance Typeable Char where
    typeRep = SimpleTypeRep $(iowitness [t|Char|])

instance Typeable Int where
    typeRep = SimpleTypeRep $(iowitness [t|Int|])

cast ::
       forall (a :: Type) (b :: Type). (Typeable a, Typeable b)
    => a
    -> Maybe b
cast a = do
    Refl :: a :~: b <- testEquality typeRep typeRep
    return a

gcast ::
       forall (k :: Type) (a :: k) (b :: k) (c :: k -> Type). (Typeable a, Typeable b)
    => c a
    -> Maybe (c b)
gcast ca = do
    Refl :: a :~: b <- testEquality typeRep typeRep
    return ca

-- | given representations of @a@ and @b@, make a representation of @a -> b@
mkFunTy :: TypeRep a -> TypeRep b -> TypeRep (a -> b)
mkFunTy ta tb = ApplyTypeRep (ApplyTypeRep (typeRep :: TypeRep (->)) ta) tb

-- | given representations of @a -> b@ and @a@, make a representation of @b@ (otherwise not)
funResultTy :: TypeRep (a -> b) -> TypeRep a -> Maybe (TypeRep b)
funResultTy (ApplyTypeRep (ApplyTypeRep repFn' ta') tb') ta = do
    Refl <- testEquality repFn' (typeRep :: TypeRep (->))
    Refl <- testEquality ta' ta
    return tb'
funResultTy _ _ = Nothing

mkAppTy :: forall (k1 :: Type) (k2 :: Type) (f :: k1 -> k2) (a :: k1). TypeRep f -> TypeRep a -> TypeRep (f a)
mkAppTy = ApplyTypeRep