packages feed

hoq-0.1.0.0: src/TypeChecking/Context.hs

{-# LANGUAGE GADTs #-}

module TypeChecking.Context where

import Control.Monad

import Syntax.Scope

data Ctx s f b a where
    Nil  :: Ctx s f b b
    Snoc :: Ctx s f b a -> s -> f a -> Ctx s f b (Scoped a)

(+++) :: Ctx s f a b -> Ctx s f b c -> Ctx s f a c
ctx +++ Nil = ctx
ctx +++ Snoc ctx' s t = Snoc (ctx +++ ctx') s t

lengthCtx :: Ctx s f b a -> Int
lengthCtx Nil = 0
lengthCtx (Snoc ctx _ _) = lengthCtx ctx + 1

lookupCtx :: (Monad g, Functor f, Eq s) => s -> Ctx s f b a -> Maybe (g a, f a)
lookupCtx _ Nil = Nothing
lookupCtx s (Snoc ctx s' t) = if s == s'
    then Just (return Bound, fmap Free t)
    else fmap (\(te, ty) -> (liftM Free te, fmap Free ty)) (lookupCtx s ctx)

close :: Monad f => Ctx b g b a -> f a -> f b
close Nil            t = t
close (Snoc ctx s _) t = close ctx $ t >>= \v -> return $ case v of
    Bound  -> liftBase ctx s
    Free a -> a

liftBase :: Ctx s f b a -> b -> a
liftBase Nil = id
liftBase (Snoc ctx _ _) = Free . liftBase ctx

abstractTermInCtx :: Ctx s g b a -> f a -> Scope s f b
abstractTermInCtx ctx term = go ctx (ScopeTerm term)
  where
    go :: Ctx s g b a -> Scope s f a -> Scope s f b
    go Nil t = t
    go (Snoc ctx s _) t = go ctx (Scope s t)