zuramaru-0.1.0.0: src/Maru/Type/TypeLevel.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
-- | Dependent types (Please see 'Maru.QQ')
module Maru.Type.TypeLevel
( HighSExpr (..)
, Sing (..)
) where
import Data.Proxy (Proxy(..))
import Data.Singletons (SingI(..), Sing, SingKind(..), SomeSing(..))
import Data.Type.Bool (type (&&))
import Data.Type.Equality (type (==))
import GHC.TypeLits (Symbol, symbolVal, Nat, natVal, KnownSymbol, KnownNat)
import Maru.Type (SExpr(..), MaruSymbol(..))
import qualified Data.Text as T
-- | A dependent type for 'SExpr' (Please see 'Maru.QQ.parse')
data HighSExpr = HCons HighSExpr HighSExpr
| HQuote HighSExpr
| HAtomInt Nat
| HAtomBool Bool
| HAtomSymbol Symbol
| HNil
data instance Sing (a :: HighSExpr) :: * where
HAtomSymbolS :: MaruSymbol -> Sing ('HAtomSymbol s)
HAtomBoolS :: Bool -> Sing ('HAtomBool x)
HAtomIntS :: Int -> Sing ('HAtomInt n)
HNilS :: Sing 'HNil
HQuoteS :: Sing x -> Sing ('HQuote x)
HConsS :: Sing x -> Sing y -> Sing ('HCons x y)
instance SingI 'HNil where
sing :: Sing 'HNil
sing = HNilS
instance KnownSymbol s => SingI ('HAtomSymbol s) where
sing :: Sing ('HAtomSymbol s)
sing = HAtomSymbolS . MaruSymbol . T.pack $ symbolVal (Proxy :: Proxy s)
instance SingI ('HAtomBool 'True) where
sing :: Sing ('HAtomBool 'True)
sing = HAtomBoolS True
instance SingI ('HAtomBool 'False) where
sing :: Sing ('HAtomBool 'False)
sing = HAtomBoolS False
instance KnownNat n => SingI ('HAtomInt n) where
sing :: Sing ('HAtomInt n)
sing = HAtomIntS . fromInteger $ natVal (Proxy :: Proxy n)
instance SingI x => SingI ('HQuote x) where
sing :: Sing ('HQuote x)
sing = let x' = sing :: Sing x
in HQuoteS x'
instance (SingI x, SingI y) => SingI ('HCons x y) where
sing :: Sing ('HCons x y)
sing = let x' = sing :: Sing x
y' = sing :: Sing y
in HConsS x' y'
instance SingKind HighSExpr where
type DemoteRep HighSExpr = SExpr
fromSing HNilS = Nil
fromSing (HAtomSymbolS s) = AtomSymbol s
fromSing (HAtomBoolS x) = AtomBool x
fromSing (HAtomIntS n) = AtomInt n
fromSing (HQuoteS x) = Quote (fromSing x)
fromSing (HConsS x y) = Cons (fromSing x) (fromSing y)
toSing Nil = SomeSing HNilS
toSing (AtomSymbol s) = SomeSing $ HAtomSymbolS s
toSing (AtomBool x) = SomeSing $ HAtomBoolS x
toSing (AtomInt n) = SomeSing $ HAtomIntS n
toSing (Quote x) = case toSing x of
SomeSing x' -> SomeSing $ HQuoteS x'
toSing (Cons x y) = case (toSing x, toSing y) of
(SomeSing x', SomeSing y') -> SomeSing $ HConsS x' y'
type instance 'HNil == 'HNil = 'True
type instance 'HAtomInt x == 'HAtomInt y = x == y
type instance 'HAtomBool x == 'HAtomBool y = x == y
type instance 'HAtomSymbol x == 'HAtomSymbol y = x == y
type instance 'HQuote x == 'HQuote y = x == y
type instance 'HCons x1 y1 == 'HCons x2 y2 = x1 == x2 && y1 == y2