Agda-2.3.2.2: src/prototyping/nameless/Syntax.hs
module Syntax where
import Control.Monad
import Stack
import Name
data Term = Free Name
| Bound Int
| App Term Term
| Lam Scope
| Pi Term Scope
| Set
deriving (Show, Eq)
data Scope = Scope { varName :: String, unScope :: Term }
deriving (Show, Eq)
topName :: Name -> String
topName Empty = "noname"
topName (_ :< (s, _)) = s
abstract :: Name -> Term -> Scope
abstract me e = Scope (topName me) $ letmeB 0 e
where
letmeB this (Free you)
| you == me = Bound this
| otherwise = Free you
letmeB this (Bound that) = Bound that
letmeB this (App e1 e2) = App (letmeB this e1) (letmeB this e2)
letmeB this (Lam (Scope x e)) = Lam (Scope x $ letmeB (this + 1) e)
letmeB this (Pi e1 (Scope x e2)) = Pi (letmeB this e1)
(Scope x $ letmeB (this + 1) e2)
letmeB this Set = Set
instantiate :: Term -> Scope -> Term
instantiate what (Scope _ body) = what'sB 0 body
where
what'sB this (Bound that)
| this == that = what
| otherwise = Bound that
what'sB this (Free you) = Free you
what'sB this (App e1 e2) = App (what'sB this e1) (what'sB this e2)
what'sB this (Lam (Scope x body)) = Lam (Scope x $ what'sB (this + 1) body)
what'sB this (Pi e (Scope x body)) = Pi (what'sB this e)
(Scope x $ what'sB (this + 1) body)
what'sB this Set = Set
substitute :: Term -> Name -> Term -> Term
substitute image x = instantiate image . abstract x
lam :: Name -> Term -> Term
lam x e = Lam $ abstract x e
infix 3 :<-
data Binding = Name :<- Term
type Telescope = [Binding]
type Context = Stack Binding
infixr 4 -->, -->>
(-->) :: Binding -> Term -> Term
(x :<- a) --> b = Pi a $ abstract x b
(-->>) :: Context -> Term -> Term
Empty -->> a = a
cxt :< b -->> a = cxt -->> b --> a
piView :: Monad m => Agency (Term -> m (Binding, Term))
piView me v = case v of
Pi a b -> return (me :<- a, instantiate (Free me) b)
_ -> fail "piView: not a Pi"
data PrefixView = PrefixV Context Term
prefixView :: String -> Agency (Term -> PrefixView)
prefixView x me thing = introduce 0 (PrefixV Empty thing) where
introduce :: Int -> PrefixView -> PrefixView
introduce i (PrefixV cxt a) =
case piView (me :< (x, i)) thing of
Just (bnd, b) -> introduce (i + 1) $ PrefixV (cxt :< bnd) b
Nothing -> PrefixV cxt a
-- weaken A (Δ -> B) = Δ -> A -> B
weaken :: Agency (Term -> Term -> Term)
weaken me dom a = doms -->> (me <: "y" :<- dom) --> range
where
PrefixV doms range = prefixView "x" me a
infixl 9 $$
($$) :: Term -> [Term] -> Term
v $$ [] = v
v $$ (u : us) = App v u $$ us
data AppView = AppV Term [Term]
appView :: Term -> AppView
appView v = peel v [] where
peel (App v u) us = peel v (u : us)
peel v us = AppV v us