module Encoded.Term import Data.Vect import Encoded.Bool import Encoded.Container import Encoded.Pair import Encoded.Sum import Encoded.Vect import Term.Syntax %ambiguity_depth 6 %prefix_record_projections off -- Utilities ---------------------- rec : Nat -> a -> (a -> a) -> a rec 0 z s = z rec (S k) z s = s (rec k z s) AppVect : forall ctx. {ty, ty' : Ty} -> Term (rec k ty' (ty ~>)) ctx -> Vect k (Term ty ctx) -> Term ty' ctx AppVect f [] = f AppVect f (t :: ts) = AppVect (App f t) ts -- Definition ------------------------------------------------------------------ TermC : Container TermC = Cases [<(Just N, 0) -- Var , (Nothing, 0) -- Zero , (Nothing, 1) -- Suc , (Nothing, 3) -- Rec , (Nothing, 1) -- Abs , (Nothing, 2) -- App ] export Term : Ty Term = W TermC -- Smart Constructors ---------------------------------------------------------- export Var : Term (N ~> Term) ctx Var = let i = There $ There $ There $ There $ There Here in Abs' (\n => App (intro {c = TermC} . tag i) [ Term) ctx Suc = let i = There $ There $ There Here in Abs' (\t => App (intro {c = TermC} . tag i) [ Term ~> Term ~> Term) ctx Rec = let i = There $ There Here in AbsAll [<_,_,_] (\[ App (intro {c = TermC} . tag i) [ Term) ctx Abs = let i = There Here in Abs' (\t => App (intro {c = TermC} . tag i) [ Term ~> Term) ctx App = let i = Here in AbsAll [<_,_] (\[ App (intro {c = TermC} . tag i) [ Ty EliminatorTy ty = (N ~> ty) * (ty) * (ty ~> ty) * (ty ~> ty ~> ty ~> ty) * (ty ~> ty) * (ty ~> ty ~> ty) public export record Eliminator (ty : Ty) (ctx : SnocList Ty) where constructor MkElim var : Term (N ~> ty) ctx zero : Term ty ctx suc : Term (ty ~> ty) ctx rec : Term (ty ~> ty ~> ty ~> ty) ctx abs : Term (ty ~> ty) ctx app : Term (ty ~> ty ~> ty) ctx %name Eliminator elim export unpack : {ty : Ty} -> Term (EliminatorTy ty) ctx -> Eliminator ty ctx unpack t = MkElim { var = App (fst . fst . fst . fst . fst) [ Eliminator ty ctx -> Term (EliminatorTy ty) ctx pack elim = App pair [ Term (EliminatorTy ty ~> Term ~> ty) ctx Elim = Abs' (\e => let el = unpack e in App (elim {c = TermC}) [ AppVect (shift el.suc) (toVect v)) , Abs' (\v => AppVect (shift el.rec) (toVect v)) , Abs' (\v => AppVect (shift el.abs) (toVect v)) , Abs' (\v => AppVect (shift el.app) (toVect v)) ]) where public export DiscriminatorTy : Ty -> Ty DiscriminatorTy ty = (N ~> ty) * (ty) * (Term ~> ty) * (Term ~> Term ~> Term ~> ty) * (Term ~> ty) * (Term ~> Term ~> ty) public export record Discriminator (ty : Ty) (ctx : SnocList Ty) where constructor MkDiscrim var : Term (N ~> ty) ctx zero : Term ty ctx suc : Term (Term ~> ty) ctx rec : Term (Term ~> Term ~> Term ~> ty) ctx abs : Term (Term ~> ty) ctx app : Term (Term ~> Term ~> ty) ctx %name Eliminator elim export unpackDisc : {ty : Ty} -> Term (DiscriminatorTy ty) ctx -> Discriminator ty ctx unpackDisc t = MkDiscrim { var = App (fst . fst . fst . fst . fst) [ Discriminator ty ctx -> Term (DiscriminatorTy ty) ctx packDisc elim = App pair [ Term (DiscriminatorTy ty ~> Term ~> ty) ctx Inspect = Abs' (\e => let el = unpackDisc e in App (inspect {c = TermC}) [ AppVect (shift el.suc) (toVect v)) , Abs' (\v => AppVect (shift el.rec) (toVect v)) , Abs' (\v => AppVect (shift el.abs) (toVect v)) , Abs' (\v => AppVect (shift el.app) (toVect v)) ]) -- Weakening ------------------------------------------------------------------- liftNat : Term ((N ~> N) ~> (N ~> N)) ctx liftNat = AbsAll [<_,_] (\[ App if' [ N) ~> Term) ctx WeakenElim = MkElim { var = AbsAll [<_,_] (\[ App (Var . f) [ Suc . t) , rec = AbsAll [<_,_,_,_] (\[ App Rec [ Abs . t . liftNat) , app = AbsAll [<_,_,_] (\[ App App [ N) ~> Term ~> Term) ctx weaken = AbsAll [<_,_] (\[ App Elim [ Term) ~> (N ~> Term)) ctx liftTerm = AbsAll [<_,_] (\[ App if' [ Term) ~> Term) ctx SubstElim = MkElim { var = AbsAll [<_,_] (\[ App f [ Suc . t) , rec = AbsAll [<_,_,_,_] (\[ App Rec [ Abs . t . liftTerm) , app = AbsAll [<_,_,_] (\[ App App [ Term) ~> Term ~> Term) ctx subst = AbsAll [<_,_] (\[ App Elim [ B ~> Term * B) ctx AppDisc = MkDiscrim { var = fallthrough . Var , zero = App fallthrough [ App fallthrough [ App pair [ App if' [ App fallthrough [ Term ~> B ~> Term * B) ctx fallthrough = AbsAll [<_,_,_] (\[ App pair [ Term ~> B ~> Term * B) ctx RecDisc = MkDiscrim { var = fallthrough . Var , zero = AbsAll [<_,_,_] (\[ App pair [ App pair [ App fallthrough [ App fallthrough [ Term ~> Term ~> B ~> Term * B) ctx fallthrough = AbsAll [<_,_,_,_] (\[ App pair [ App pair [ App Inspect [ App Inspect [ Term ~> Term) ctx reduce = Abs' (\n => Rec n Id (Abs' (\rec => (Abs' {ty = Term * B} (\ub => App if' [