{-# LANGUAGE DataKinds
, PolyKinds
, TypeOperators
, GADTs
, TypeFamilies
, FlexibleInstances
, Rank2Types
, UndecidableInstances
, ScopedTypeVariables
#-}
{-# OPTIONS_GHC -Wall -fwarn-tabs #-}
module Language.Hakaru.Types.Sing
( Sing(..)
, SingI(..), singOf
, sBool
, sUnit
, sPair
, sEither
, sList
, sMaybe
, sUnMeasure
, sUnArray
, sUnPair, sUnPair'
, sUnEither, sUnEither'
, sUnList
, sUnMaybe
, sUnFun
, someSSymbol, ssymbolVal
, sSymbol_Bool
, sSymbol_Unit
, sSymbol_Pair
, sSymbol_Either
, sSymbol_List
, sSymbol_Maybe
) where
import qualified GHC.TypeLits as TL
import Unsafe.Coerce
import Data.Proxy
import Language.Hakaru.Syntax.IClasses
import Language.Hakaru.Types.DataKind
infixr 0 `SFun`
infixr 6 `SPlus`
infixr 7 `SEt`
data family Sing (a :: k) :: *
class SingI (a :: k) where sing :: Sing a
singOf :: SingI a => proxy a -> Sing a
singOf _ = sing
data instance Sing (a :: Hakaru) where
SNat :: Sing 'HNat
SInt :: Sing 'HInt
SProb :: Sing 'HProb
SReal :: Sing 'HReal
SMeasure :: !(Sing a) -> Sing ('HMeasure a)
SArray :: !(Sing a) -> Sing ('HArray a)
SFun :: !(Sing a) -> !(Sing b) -> Sing (a ':-> b)
SData :: !(Sing t) -> !(Sing (Code t)) -> Sing (HData' t)
instance Eq (Sing (a :: Hakaru)) where
(==) = eq1
instance Eq1 (Sing :: Hakaru -> *) where
eq1 x y = maybe False (const True) (jmEq1 x y)
instance JmEq1 (Sing :: Hakaru -> *) where
jmEq1 SNat SNat = Just Refl
jmEq1 SInt SInt = Just Refl
jmEq1 SProb SProb = Just Refl
jmEq1 SReal SReal = Just Refl
jmEq1 (SMeasure a) (SMeasure b) =
jmEq1 a b >>= \Refl ->
Just Refl
jmEq1 (SArray a) (SArray b) =
jmEq1 a b >>= \Refl ->
Just Refl
jmEq1 (SFun a1 a2) (SFun b1 b2) =
jmEq1 a1 b1 >>= \Refl ->
jmEq1 a2 b2 >>= \Refl ->
Just Refl
jmEq1 (SData con1 code1) (SData con2 code2) =
jmEq1 con1 con2 >>= \Refl ->
jmEq1 code1 code2 >>= \Refl ->
Just Refl
jmEq1 _ _ = Nothing
instance Show (Sing (a :: Hakaru)) where
showsPrec = showsPrec1
show = show1
instance Show1 (Sing :: Hakaru -> *) where
showsPrec1 p s =
case s of
SNat -> showString "SNat"
SInt -> showString "SInt"
SProb -> showString "SProb"
SReal -> showString "SReal"
SMeasure s1 -> showParen_1 p "SMeasure" s1
SArray s1 -> showParen_1 p "SArray" s1
SFun s1 s2 -> showParen_11 p "SFun" s1 s2
SData s1 s2 -> showParen_11 p "SData" s1 s2
instance SingI 'HNat where sing = SNat
instance SingI 'HInt where sing = SInt
instance SingI 'HProb where sing = SProb
instance SingI 'HReal where sing = SReal
instance (SingI a) => SingI ('HMeasure a) where sing = SMeasure sing
instance (SingI a) => SingI ('HArray a) where sing = SArray sing
instance (SingI a, SingI b) => SingI (a ':-> b) where sing = SFun sing sing
instance (sop ~ Code t, SingI t, SingI sop) => SingI ('HData t sop) where
sing = SData sing sing
sUnMeasure :: Sing ('HMeasure a) -> Sing a
sUnMeasure (SMeasure a) = a
sUnArray :: Sing ('HArray a) -> Sing a
sUnArray (SArray a) = a
sUnit :: Sing HUnit
sUnit =
SData (STyCon sSymbol_Unit)
(SDone `SPlus` SVoid)
sBool :: Sing HBool
sBool =
SData (STyCon sSymbol_Bool)
(SDone `SPlus` SDone `SPlus` SVoid)
sPair :: Sing a -> Sing b -> Sing (HPair a b)
sPair a b =
SData (STyCon sSymbol_Pair `STyApp` a `STyApp` b)
((SKonst a `SEt` SKonst b `SEt` SDone) `SPlus` SVoid)
sUnPair :: Sing (HPair a b) -> (Sing a, Sing b)
sUnPair (SData (STyApp (STyApp (STyCon _) a) b) _) = (a,b)
sUnPair _ = error "sUnPair: the impossible happened"
sUnPair' :: Sing (x :: Hakaru)
-> (forall (a :: Hakaru) (b :: Hakaru) .
(TypeEq x (HPair a b), Sing a, Sing b) -> r)
-> Maybe r
sUnPair' (SData (STyApp (STyApp (STyCon t) a) b) _) k
| Just Refl <- jmEq1 t sSymbol_Pair = Just $ k (Refl, a, b)
sUnPair' _ _ = Nothing
sEither :: Sing a -> Sing b -> Sing (HEither a b)
sEither a b =
SData (STyCon sSymbol_Either `STyApp` a `STyApp` b)
((SKonst a `SEt` SDone) `SPlus` (SKonst b `SEt` SDone)
`SPlus` SVoid)
sUnEither :: Sing (HEither a b) -> (Sing a, Sing b)
sUnEither (SData (STyApp (STyApp (STyCon _) a) b) _) = (a,b)
sUnEither _ = error "sUnEither: the impossible happened"
sUnEither' :: Sing (x :: Hakaru)
-> (forall (a :: Hakaru) (b :: Hakaru) .
(TypeEq x (HEither a b), Sing a, Sing b) -> r)
-> Maybe r
sUnEither' (SData (STyApp (STyApp (STyCon t) a) b) _) k
| Just Refl <- jmEq1 t sSymbol_Either = Just $ k (Refl, a, b)
sUnEither' _ _ = Nothing
sList :: Sing a -> Sing (HList a)
sList a =
SData (STyCon sSymbol_List `STyApp` a)
(SDone `SPlus` (SKonst a `SEt` SIdent `SEt` SDone) `SPlus` SVoid)
sUnList :: Sing (HList a) -> Sing a
sUnList (SData (STyApp (STyCon _) a) _) = a
sUnList _ = error "sUnList: the impossible happened"
sMaybe :: Sing a -> Sing (HMaybe a)
sMaybe a =
SData (STyCon sSymbol_Maybe `STyApp` a)
(SDone `SPlus` (SKonst a `SEt` SDone) `SPlus` SVoid)
sUnMaybe :: Sing (HMaybe a) -> Sing a
sUnMaybe (SData (STyApp (STyCon _) a) _) = a
sUnMaybe _ = error "sUnMaybe: the impossible happened"
sUnFun :: Sing (a ':-> b) -> (Sing a, Sing b)
sUnFun (SFun a b) = (a,b)
data instance Sing (a :: HakaruCon) where
STyCon :: !(Sing s) -> Sing ('TyCon s :: HakaruCon)
STyApp :: !(Sing a) -> !(Sing b) -> Sing (a ':@ b :: HakaruCon)
instance Eq (Sing (a :: HakaruCon)) where
(==) = eq1
instance Eq1 (Sing :: HakaruCon -> *) where
eq1 x y = maybe False (const True) (jmEq1 x y)
instance JmEq1 (Sing :: HakaruCon -> *) where
jmEq1 (STyCon s) (STyCon z) = jmEq1 s z >>= \Refl -> Just Refl
jmEq1 (STyApp f a) (STyApp g b) =
jmEq1 f g >>= \Refl ->
jmEq1 a b >>= \Refl ->
Just Refl
jmEq1 _ _ = Nothing
instance Show (Sing (a :: HakaruCon)) where
showsPrec = showsPrec1
show = show1
instance Show1 (Sing :: HakaruCon -> *) where
showsPrec1 p (STyCon s1) = showParen_1 p "STyCon" s1
showsPrec1 p (STyApp s1 s2) = showParen_11 p "STyApp" s1 s2
instance TL.KnownSymbol s => SingI ('TyCon s :: HakaruCon) where
sing = STyCon sing
instance (SingI a, SingI b) => SingI ((a ':@ b) :: HakaruCon) where
sing = STyApp sing sing
data instance Sing (s :: Symbol) where
SingSymbol :: TL.KnownSymbol s => Sing (s :: Symbol)
sSymbol_Bool :: Sing "Bool"
sSymbol_Bool = SingSymbol
sSymbol_Unit :: Sing "Unit"
sSymbol_Unit = SingSymbol
sSymbol_Pair :: Sing "Pair"
sSymbol_Pair = SingSymbol
sSymbol_Either :: Sing "Either"
sSymbol_Either = SingSymbol
sSymbol_List :: Sing "List"
sSymbol_List = SingSymbol
sSymbol_Maybe :: Sing "Maybe"
sSymbol_Maybe = SingSymbol
someSSymbol :: String -> (forall s . Sing (s :: Symbol) -> k) -> k
someSSymbol s k = case TL.someSymbolVal s of { TL.SomeSymbol (_::Proxy s) -> k (SingSymbol :: Sing s) }
ssymbolVal :: forall s. Sing (s :: Symbol) -> String
ssymbolVal SingSymbol = TL.symbolVal (Proxy :: Proxy s)
instance Eq (Sing (s :: Symbol)) where
(==) = eq1
instance Eq1 (Sing :: Symbol -> *) where
eq1 x y = maybe False (const True) (jmEq1 x y)
instance JmEq1 (Sing :: Symbol -> *) where
jmEq1 x@SingSymbol y@SingSymbol
| TL.symbolVal x == TL.symbolVal y = Just (unsafeCoerce Refl)
| otherwise = Nothing
instance Show (Sing (s :: Symbol)) where
showsPrec = showsPrec1
show = show1
instance Show1 (Sing :: Symbol -> *) where
showsPrec1 _ s@SingSymbol =
showParen True
( showString "SingSymbol :: Sing "
. showString (show $ TL.symbolVal s)
)
instance TL.KnownSymbol s => SingI (s :: Symbol) where
sing = SingSymbol
data instance Sing (a :: [[HakaruFun]]) where
SVoid :: Sing ('[] :: [[HakaruFun]])
SPlus
:: !(Sing xs)
-> !(Sing xss)
-> Sing ((xs ': xss) :: [[HakaruFun]])
instance Eq (Sing (a :: [[HakaruFun]])) where
(==) = eq1
instance Eq1 (Sing :: [[HakaruFun]] -> *) where
eq1 x y = maybe False (const True) (jmEq1 x y)
instance JmEq1 (Sing :: [[HakaruFun]] -> *) where
jmEq1 SVoid SVoid = Just Refl
jmEq1 (SPlus x xs) (SPlus y ys) =
jmEq1 x y >>= \Refl ->
jmEq1 xs ys >>= \Refl ->
Just Refl
jmEq1 _ _ = Nothing
instance Show (Sing (a :: [[HakaruFun]])) where
showsPrec = showsPrec1
show = show1
instance Show1 (Sing :: [[HakaruFun]] -> *) where
showsPrec1 _ SVoid = showString "SVoid"
showsPrec1 p (SPlus s1 s2) = showParen_11 p "SPlus" s1 s2
instance SingI ('[] :: [[HakaruFun]]) where
sing = SVoid
instance (SingI xs, SingI xss) => SingI ((xs ': xss) :: [[HakaruFun]]) where
sing = SPlus sing sing
data instance Sing (a :: [HakaruFun]) where
SDone :: Sing ('[] :: [HakaruFun])
SEt :: !(Sing x) -> !(Sing xs) -> Sing ((x ': xs) :: [HakaruFun])
instance Eq (Sing (a :: [HakaruFun])) where
(==) = eq1
instance Eq1 (Sing :: [HakaruFun] -> *) where
eq1 x y = maybe False (const True) (jmEq1 x y)
instance JmEq1 (Sing :: [HakaruFun] -> *) where
jmEq1 SDone SDone = Just Refl
jmEq1 (SEt x xs) (SEt y ys) =
jmEq1 x y >>= \Refl ->
jmEq1 xs ys >>= \Refl ->
Just Refl
jmEq1 _ _ = Nothing
instance Show (Sing (a :: [HakaruFun])) where
showsPrec = showsPrec1
show = show1
instance Show1 (Sing :: [HakaruFun] -> *) where
showsPrec1 _ SDone = showString "SDone"
showsPrec1 p (SEt s1 s2) = showParen_11 p "SEt" s1 s2
instance SingI ('[] :: [HakaruFun]) where
sing = SDone
instance (SingI x, SingI xs) => SingI ((x ': xs) :: [HakaruFun]) where
sing = SEt sing sing
data instance Sing (a :: HakaruFun) where
SIdent :: Sing 'I
SKonst :: !(Sing a) -> Sing ('K a)
instance Eq (Sing (a :: HakaruFun)) where
(==) = eq1
instance Eq1 (Sing :: HakaruFun -> *) where
eq1 x y = maybe False (const True) (jmEq1 x y)
instance JmEq1 (Sing :: HakaruFun -> *) where
jmEq1 SIdent SIdent = Just Refl
jmEq1 (SKonst a) (SKonst b) = jmEq1 a b >>= \Refl -> Just Refl
jmEq1 _ _ = Nothing
instance Show (Sing (a :: HakaruFun)) where
showsPrec = showsPrec1
show = show1
instance Show1 (Sing :: HakaruFun -> *) where
showsPrec1 _ SIdent = showString "SIdent"
showsPrec1 p (SKonst s1) = showParen_1 p "SKonst" s1
instance SingI 'I where
sing = SIdent
instance (SingI a) => SingI ('K a) where
sing = SKonst sing