{-# LANGUAGE Safe #-}
module DeBruijn.Env (
Env (EmptyEnv, (:>)),
lookupEnv,
sizeEnv,
tabulateEnv,
) where
import Data.Kind (Type)
import DeBruijn.Ctx
import DeBruijn.Idx
import DeBruijn.Size
-- $setup
-- >>> import DeBruijn
-- >>> import Data.Foldable (toList)
-------------------------------------------------------------------------------
-- Environment
-------------------------------------------------------------------------------
-- | Environment
--
-- >>> EmptyEnv :> 'a' :> 'b'
-- EmptyEnv :> 'a' :> 'b'
--
type Env :: Ctx -> Type -> Type
data Env ctx a where
EmptyEnv :: Env EmptyCtx a
(:>) :: Env ctx a -> a -> Env (S ctx) a
infixl 5 :>
-------------------------------------------------------------------------------
-- Instances
-------------------------------------------------------------------------------
deriving instance Functor (Env ctx)
-- |
--
-- >>> toList (tabulateEnv S3 id)
-- [2,1,0]
--
deriving instance Foldable (Env ctx)
-- |
--
-- >>> traverse print (tabulateEnv S3 id)
-- 2
-- 1
-- 0
-- EmptyEnv :> () :> () :> ()
--
deriving instance Traversable (Env ctx)
instance Show a => Show (Env ctx a) where
showsPrec _ EmptyEnv = showString "EmptyEnv"
showsPrec d (xs :> x) = showParen (d > 5)
$ showsPrec 5 xs
. showString " :> "
. showsPrec 6 x
-------------------------------------------------------------------------------
-- Combinators
-------------------------------------------------------------------------------
-- | Lookup in the context.
--
-- >>> lookupEnv IZ (EmptyEnv :> 'a' :> 'b')
-- 'b'
--
lookupEnv :: Idx ctx -> Env ctx a -> a
lookupEnv IZ (_ :> x) = x
lookupEnv (IS n) (xs :> _) = lookupEnv n xs
-- | Size of the environment.
--
-- >>> sizeEnv (EmptyEnv :> 'a' :> 'b')
-- 2
--
sizeEnv :: Env n a -> Size n
sizeEnv EmptyEnv = SZ
sizeEnv (xs :> _) = SS (sizeEnv xs)
tabulateEnv :: Size ctx -> (Idx ctx -> a) -> Env ctx a
tabulateEnv SZ _ = EmptyEnv
tabulateEnv (SS s) f = tabulateEnv s (f . IS) :> f IZ