diff options
Diffstat (limited to 'src/Total/Term')
-rw-r--r-- | src/Total/Term/CoDebruijn.idr | 280 |
1 files changed, 243 insertions, 37 deletions
diff --git a/src/Total/Term/CoDebruijn.idr b/src/Total/Term/CoDebruijn.idr index 00abc31..0efcdbb 100644 --- a/src/Total/Term/CoDebruijn.idr +++ b/src/Total/Term/CoDebruijn.idr @@ -7,6 +7,8 @@ import Total.Term %prefix_record_projections off +-- Definition ------------------------------------------------------------------ + public export data CoTerm : Ty -> SnocList Ty -> Type where Var : CoTerm ty [<ty] @@ -22,90 +24,294 @@ public export FullTerm : Ty -> SnocList Ty -> Type FullTerm ty ctx = Thinned (CoTerm ty) ctx -export +-- Smart Constructors ---------------------------------------------------------- + +public export var : Len ctx => Elem ty ctx -> FullTerm ty ctx var i = Var `Over` point i -export +public export abs : FullTerm ty' (ctx :< ty) -> FullTerm (ty ~> ty') ctx abs = map Abs . MkBound (S Z) -export +public export app : {ty : Ty} -> FullTerm (ty ~> ty') ctx -> FullTerm ty ctx -> FullTerm ty' ctx app t u = map App (MkPair t u) -export +public export zero : Len ctx => FullTerm N ctx zero = Zero `Over` empty -export +public export suc : FullTerm N ctx -> FullTerm N ctx suc = map Suc -export +public export rec : FullTerm N ctx -> FullTerm ty ctx -> FullTerm (ty ~> ty) ctx -> FullTerm ty ctx rec t u v = map Rec $ MkPair t (MkPair u v) -export -wkn : FullTerm ty ctx -> ctx `Thins` ctx' -> FullTerm ty ctx' -wkn (t `Over` thin) thin' = t `Over` thin' . thin +-- Substitutions --------------------------------------------------------------- public export data CoTerms : SnocList Ty -> SnocList Ty -> Type where - Base : ctx `Thins` ctx' -> CoTerms ctx ctx' + Lin : CoTerms [<] ctx' (:<) : CoTerms ctx ctx' -> FullTerm ty ctx' -> CoTerms (ctx :< ty) ctx' %name CoTerms sub -export +public export +index : CoTerms ctx ctx' -> Elem ty ctx -> FullTerm ty ctx' +index (sub :< t) Here = t +index (sub :< t) (There i) = index sub i + +public export +wknAll : CoTerms ctx ctx' -> ctx' `Thins` ctx'' -> CoTerms ctx ctx'' +wknAll [<] thin = [<] +wknAll (sub :< t) thin = wknAll sub thin :< wkn t thin + +public export shift : CoTerms ctx ctx' -> CoTerms ctx (ctx' :< ty) -shift (Base thin) = Base (Drop thin) -shift (sub :< (t `Over` thin)) = shift sub :< (t `Over` Drop thin) +shift [<] = [<] +shift (sub :< t) = shift sub :< drop t -export +public export lift : Len ctx' => CoTerms ctx ctx' -> CoTerms (ctx :< ty) (ctx' :< ty) lift sub = shift sub :< var Here -export +public export restrict : CoTerms ctx' ctx'' -> ctx `Thins` ctx' -> CoTerms ctx ctx'' -restrict (Base thin') thin = Base (thin' . thin) +restrict [<] Empty = [<] restrict (sub :< t) (Drop thin) = restrict sub thin restrict (sub :< t) (Keep thin) = restrict sub thin :< t -export +public export +Base : (len : Len ctx') => ctx `Thins` ctx' -> CoTerms ctx ctx' +Base Empty = [<] +Base {len = S k} (Drop thin) = shift (Base thin) +Base {len = S k} (Keep thin) = lift (Base thin) + +-- Substitution Operation ------------------------------------------------------ + +public export subst : Len ctx' => FullTerm ty ctx -> CoTerms ctx ctx' -> FullTerm ty ctx' +public export subst' : Len ctx' => CoTerm ty ctx -> CoTerms ctx ctx' -> FullTerm ty ctx' subst (t `Over` thin) sub = subst' t (restrict sub thin) -subst' t (Base thin) = t `Over` thin -subst' Var (sub :< t) = t -subst' (Abs (MakeBound t (Drop Empty))) sub@(_ :< _) = abs (subst' t $ shift sub) -subst' (Abs (MakeBound t (Keep Empty))) sub@(_ :< _) = abs (subst' t $ lift sub) -subst' (App (MakePair t u _)) sub@(_ :< _) = app (subst t sub) (subst u sub) -subst' (Suc t) sub@(_ :< _) = suc (subst' t sub) -subst' (Rec (MakePair t (MakePair u v _ `Over` thin) _)) sub@(_ :< _) = +subst' Var sub = index sub Here +subst' (Abs (MakeBound t (Drop Empty))) sub = abs (subst' t $ shift sub) +subst' (Abs (MakeBound t (Keep Empty))) sub = abs (subst' t $ lift sub) +subst' (App (MakePair t u _)) sub = app (subst t sub) (subst u sub) +subst' Zero sub = zero +subst' (Suc t) sub = suc (subst' t sub) +subst' (Rec (MakePair t (MakePair u v _ `Over` thin) _)) sub = rec (subst t sub) (subst u (restrict sub thin)) (subst v (restrict sub thin)) -toTerm : CoTerm ty ctx -> ctx `Thins` ctx' -> Term ctx' ty -toTerm Var thin = Var (index thin Here) -toTerm (Abs (MakeBound t (Drop Empty))) thin = Abs (toTerm t (Drop thin)) -toTerm (Abs (MakeBound t (Keep Empty))) thin = Abs (toTerm t (Keep thin)) -toTerm (App (MakePair (t `Over` thin1) (u `Over` thin2) _)) thin = - App (toTerm t (thin . thin1)) (toTerm u (thin . thin2)) -toTerm Zero thin = Zero -toTerm (Suc t) thin = Suc (toTerm t thin) -toTerm +-- Initiality ------------------------------------------------------------------ + +toTerm' : CoTerm ty ctx -> ctx `Thins` ctx' -> Term ctx' ty +toTerm' Var thin = Var (index thin Here) +toTerm' (Abs (MakeBound t (Drop Empty))) thin = Abs (toTerm' t (Drop thin)) +toTerm' (Abs (MakeBound t (Keep Empty))) thin = Abs (toTerm' t (Keep thin)) +toTerm' (App (MakePair (t `Over` thin1) (u `Over` thin2) _)) thin = + App (toTerm' t (thin . thin1)) (toTerm' u (thin . thin2)) +toTerm' Zero thin = Zero +toTerm' (Suc t) thin = Suc (toTerm' t thin) +toTerm' (Rec (MakePair (t `Over` thin1) (MakePair (u `Over` thin2) (v `Over` thin3) _ `Over` thin') _)) thin = Rec - (toTerm t (thin . thin1)) - (toTerm u ((thin . thin') . thin2)) - (toTerm v ((thin . thin') . thin3)) + (toTerm' t (thin . thin1)) + (toTerm' u ((thin . thin') . thin2)) + (toTerm' v ((thin . thin') . thin3)) + +export +toTerm : FullTerm ty ctx -> Term ctx ty +toTerm (t `Over` thin) = toTerm' t thin + +public export +toTerms : Len ctx' => CoTerms ctx ctx' -> Terms ctx' ctx +toTerms [<] = Base empty +toTerms (sub :< t) = toTerms sub :< toTerm t export Cast (FullTerm ty ctx) (Term ctx ty) where - cast (t `Over` thin) = toTerm t thin + cast = toTerm + +export +Len ctx' => Cast (CoTerms ctx ctx') (Terms ctx' ctx) where + cast = toTerms + +export +Len ctx => Cast (Term ctx ty) (FullTerm ty ctx) where + cast (Var i) = Var `Over` point i + cast (Abs t) = abs (cast t) + cast (App {ty} t u) = app {ty} (cast t) (cast u) + cast Zero = zero + cast (Suc t) = suc (cast t) + cast (Rec t u v) = rec (cast t) (cast u) (cast v) + +-- Properties ------------------------------------------------------------------ + +wknToTerm' : + (t : CoTerm ty ctx) -> + (thin : ctx `Thins` ctx') -> + (thin' : ctx' `Thins` ctx''') -> + wkn (toTerm' t thin) thin' = toTerm' t (thin' . thin) +wknToTerm' Var thin thin' = cong Var (indexHomo thin' thin Here) +wknToTerm' (Abs (MakeBound t (Drop Empty))) thin thin' = + cong Abs (wknToTerm' t (Drop thin) (Keep thin')) +wknToTerm' (Abs (MakeBound t (Keep Empty))) thin thin' = + cong Abs (wknToTerm' t (Keep thin) (Keep thin')) +wknToTerm' (App (MakePair (t `Over` thin1) (u `Over` thin2) _)) thin thin' = + rewrite sym $ assoc thin' thin thin1 in + rewrite sym $ assoc thin' thin thin2 in + cong2 App (wknToTerm' t (thin . thin1) thin') (wknToTerm' u (thin . thin2) thin') +wknToTerm' Zero thin thin' = Refl +wknToTerm' (Suc t) thin thin' = cong Suc (wknToTerm' t thin thin') +wknToTerm' + (Rec + (MakePair + (t `Over` thin1) + (MakePair (u `Over` thin2) (v `Over` thin3) _ `Over` thin'') _)) + thin + thin' = + rewrite sym $ assoc thin' thin thin1 in + rewrite sym $ assoc (thin' . thin) thin'' thin2 in + rewrite sym $ assoc thin' thin (thin'' . thin2) in + rewrite sym $ assoc thin thin'' thin2 in + rewrite sym $ assoc (thin' . thin) thin'' thin3 in + rewrite sym $ assoc thin' thin (thin'' . thin3) in + rewrite sym $ assoc thin thin'' thin3 in + cong3 Rec + (wknToTerm' t (thin . thin1) thin') + (wknToTerm' u (thin . (thin'' . thin2)) thin') + (wknToTerm' v (thin . (thin'' . thin3)) thin') + +export +wknToTerm : + (t : FullTerm ty ctx) -> + (thin : ctx `Thins` ctx') -> + wkn (toTerm t) thin = toTerm (wkn t thin) +wknToTerm (t `Over` thin') thin = wknToTerm' t thin' thin + +export +toTermVar : Len ctx => (i : Elem ty ctx) -> toTerm (var i) = Var i +toTermVar i = cong Var $ indexPoint i + +export +toTermApp : + (t : FullTerm (ty ~> ty') ctx) -> + (u : FullTerm ty ctx) -> + toTerm (app t u) = App (toTerm t) (toTerm u) +toTermApp (t `Over` thin1) (u `Over` thin2) = + cong2 App + (cong (toTerm' t) $ irrelevantEq $ triangleCorrect (coprod thin1 thin2).left) + (cong (toTerm' u) $ irrelevantEq $ triangleCorrect (coprod thin1 thin2).right) + +indexShift : + (sub : CoTerms ctx ctx') -> + (i : Elem ty ctx) -> + index (shift sub) i = drop (index sub i) +indexShift (sub :< t) Here = Refl +indexShift (sub :< t) (There i) = indexShift sub i + +indexBase : (thin : [<ty] `Thins` ctx') -> index (Base thin) Here = Var `Over` thin +indexBase (Drop thin) = trans (indexShift (Base thin) Here) (cong drop (indexBase thin)) +indexBase (Keep thin) = irrelevantEq $ cong ((Var `Over`) . Keep) $ emptyUnique empty thin + +restrictShift : + (sub : CoTerms ctx' ctx'') -> + (thin : ctx `Thins` ctx') -> + restrict (shift sub) thin = shift (restrict sub thin) +restrictShift [<] Empty = Refl +restrictShift (sub :< t) (Drop thin) = restrictShift sub thin +restrictShift (sub :< t) (Keep thin) = cong (:< drop t) (restrictShift sub thin) + +restrictBase : + (thin2 : ctx' `Thins` ctx'') -> + (thin1 : ctx `Thins` ctx') -> + CoDebruijn.restrict (Base thin2) thin1 = Base (thin2 . thin1) +restrictBase Empty Empty = Refl +restrictBase (Drop thin2) thin1 = + trans + (restrictShift (Base thin2) thin1) + (cong shift $ restrictBase thin2 thin1) +restrictBase (Keep thin2) (Drop thin1) = + trans + (restrictShift (Base thin2) thin1) + (cong shift $ restrictBase thin2 thin1) +restrictBase (Keep thin2) (Keep thin1) = + cong (:< (Var `Over` point Here)) $ + trans + (restrictShift (Base thin2) thin1) + (cong shift $ restrictBase thin2 thin1) + +substBase : + (t : CoTerm ty ctx) -> + (thin : ctx `Thins` ctx') -> + subst' t (Base thin) = t `Over` thin +substBase Var thin = indexBase thin +substBase (Abs (MakeBound t (Drop Empty))) thin = + Calc $ + |~ map Abs (MkBound (S Z) (subst' t (shift $ Base thin))) + ~~ map Abs (MkBound (S Z) (t `Over` Drop thin)) + ...(cong (map Abs . MkBound (S Z)) $ substBase t (Drop thin)) + ~~ map Abs (MakeBound t (Drop Empty) `Over` thin) + ...(Refl) + ~~ (Abs (MakeBound t (Drop Empty)) `Over` thin) + ...(Refl) +substBase (Abs (MakeBound t (Keep Empty))) thin = + Calc $ + |~ map Abs (MkBound (S Z) (subst' t (lift $ Base thin))) + ~~ map Abs (MkBound (S Z) (t `Over` Keep thin)) + ...(cong (map Abs . MkBound (S Z)) $ substBase t (Keep thin)) + ~~ map Abs (MakeBound t (Keep Empty) `Over` thin) + ...(Refl) + ~~ (Abs (MakeBound t (Keep Empty)) `Over` thin) + ...(Refl) +substBase (App (MakePair (t `Over` thin1) (u `Over` thin2) cover)) thin = + rewrite restrictBase thin thin1 in + rewrite restrictBase thin thin2 in + rewrite substBase t (thin . thin1) in + rewrite substBase u (thin . thin2) in + rewrite coprodEta thin cover in + Refl +substBase Zero thin = cong (Zero `Over`) $ irrelevantEq $ emptyUnique empty thin +substBase (Suc t) thin = cong (map Suc) $ substBase t thin +substBase + (Rec (MakePair + (t `Over` thin1) + (MakePair + (u `Over` thin2) + (v `Over` thin3) + cover' + `Over` thin') + cover)) + thin = + rewrite restrictBase thin thin1 in + rewrite restrictBase thin thin' in + rewrite restrictBase (thin . thin') thin2 in + rewrite restrictBase (thin . thin') thin3 in + rewrite substBase t (thin . thin1) in + rewrite substBase u ((thin . thin') . thin2) in + rewrite substBase v ((thin . thin') . thin3) in + rewrite coprodEta (thin . thin') cover' in + rewrite coprodEta thin cover in + Refl + +export +substId : (t : FullTerm ty ctx) -> subst t (Base Thinning.id) = t +substId (t `Over` thin) = + Calc $ + |~ subst' t (restrict (Base id) thin) + ~~ subst' t (Base $ id . thin) + ...(cong (subst' t) $ restrictBase id thin) + ~~ subst' t (Base thin) + ...(cong (subst' t . Base) $ identityLeft thin) + ~~ (t `Over` thin) + ...(substBase t thin) |