diff options
author | Chloe Brown <chloe.brown.00@outlook.com> | 2023-06-16 15:06:59 +0100 |
---|---|---|
committer | Chloe Brown <chloe.brown.00@outlook.com> | 2023-06-16 15:06:59 +0100 |
commit | 5adc1ae9357e42937a601aab57d16b2190e10536 (patch) | |
tree | 219b0bac7058abd55729990536fb93cecda7cc7b /src/Term.idr | |
parent | f910e142ce7c10f8244ecfa40e41756fb8c8a53f (diff) |
Reset using only co-de Bruijn syntax.
Diffstat (limited to 'src/Term.idr')
-rw-r--r-- | src/Term.idr | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/src/Term.idr b/src/Term.idr new file mode 100644 index 0000000..e9f6b1f --- /dev/null +++ b/src/Term.idr @@ -0,0 +1,341 @@ +module Term + +import Control.Order +import Control.Relation +import Syntax.PreorderReasoning +import Syntax.PreorderReasoning.Generic + +import public Data.SnocList.Quantifiers +import public Thinned +import public Type + +%prefix_record_projections off + +-- Definition ------------------------------------------------------------------ + +||| System T terms that use all the variables in scope. +public export +data FullTerm : Ty -> SnocList Ty -> Type where + Var : FullTerm ty [<ty] + Const : FullTerm ty' ctx -> FullTerm (ty ~> ty') ctx + Abs : FullTerm ty' (ctx :< ty) -> FullTerm (ty ~> ty') ctx + App : + {ty : Ty} -> + Pair (FullTerm (ty ~> ty')) (FullTerm ty) ctx -> + FullTerm ty' ctx + Zero : FullTerm N [<] + Suc : FullTerm N ctx -> FullTerm N ctx + Rec : + Pair (FullTerm N) (Pair (FullTerm ty) (FullTerm (ty ~> ty))) ctx -> + FullTerm ty ctx + +%name FullTerm t, u, v + +||| System T terms. +public export +Term : Ty -> SnocList Ty -> Type +Term ty ctx = Thinned (FullTerm ty) ctx + +-- Smart Constructors ---------------------------------------------------------- + +namespace Smart + export + Var : Elem ty ctx -> Term ty ctx + Var i = Var `Over` Point i + + export + Const : Term ty' ctx -> Term (ty ~> ty') ctx + Const t = map Const t + + export + Abs : Term ty' (ctx :< ty) -> Term (ty ~> ty') ctx + Abs (t `Over` Id) = Abs t `Over` Id + Abs (t `Over` Empty) = Const t `Over` Empty + Abs (t `Over` Drop thin) = Const t `Over` thin + Abs (t `Over` Keep thin) = Abs t `Over` thin + + export + App : {ty : Ty} -> Term (ty ~> ty') ctx -> Term ty ctx -> Term ty' ctx + App t u = map App $ MkPair t u + + export + Zero : Term N ctx + Zero = Zero `Over` Empty + + export + Suc : Term N ctx -> Term N ctx + Suc t = map Suc t + + export + Rec : Term N ctx -> Term ty ctx -> Term (ty ~> ty) ctx -> Term ty ctx + Rec t u v = map Rec $ MkPair t (MkPair u v) + + --- Properties + + export + varCong : {0 i, j : Elem ty ctx} -> i = j -> Var i <~> Var j + + export + shiftVar : (i : Elem ty ctx) -> shift (Var i) <~> Var (There i) + + export + constCong : {0 t, u : Term ty' ctx} -> t <~> u -> Const t <~> Const u + + export + absCong : {0 t, u : Term ty' (ctx :< ty)} -> t <~> u -> Abs t <~> Abs u + + export + appCong : + {0 t1, u1 : Term (ty ~> ty') ctx} -> + {0 t2, u2 : Term ty ctx} -> + t1 <~> u1 -> + t2 <~> u2 -> + App t1 t2 <~> App u1 u2 + + export + sucCong : {0 t, u : Term N ctx} -> t <~> u -> Suc t <~> Suc u + + export + recCong : + {0 t1, u1 : Term N ctx} -> + {0 t2, u2 : Term ty ctx} -> + {0 t3, u3 : Term (ty ~> ty) ctx} -> + t1 <~> u1 -> + t2 <~> u2 -> + t3 <~> u3 -> + Rec t1 t2 t3 <~> Rec u1 u2 u3 + recCong prf1 prf2 prf3 = + mapCong Rec + ?recCong_rhs_1 + +-- Substitution Definition ----------------------------------------------------- + +||| Substitution of variables for terms. +public export +data Subst : (ctx, ctx' : SnocList Ty) -> Type where + Base : ctx `Thins` ctx' -> Subst ctx ctx' + (:<) : Subst ctx ctx' -> Term ty ctx' -> Subst (ctx :< ty) ctx' + +%name Subst sub + +export +index : Subst ctx ctx' -> Elem ty ctx -> Term ty ctx' +index (Base thin) i = Var (index thin i) +index (sub :< v) Here = v +index (sub :< v) (There i) = index sub i + +||| Equivalence relation on substitutions. +public export +record (<~>) (sub1, sub2 : Subst ctx ctx') where + constructor MkEquivalence + equiv : forall ty. (i : Elem ty ctx) -> index sub1 i <~> index sub2 i + +%name Term.(<~>) prf + +--- Properties + +export +irrelevantEquiv : + {0 sub1, sub2 : Subst ctx ctx'} -> + (0 prf : sub1 <~> sub2) -> + sub1 <~> sub2 +irrelevantEquiv prf = MkEquivalence (\i => irrelevantEquiv $ prf.equiv i) + +export +Reflexive (Subst ctx ctx') (<~>) where + reflexive = MkEquivalence (\i => reflexive) + +export +Symmetric (Subst ctx ctx') (<~>) where + symmetric prf = MkEquivalence (\i => symmetric $ prf.equiv i) + +export +Transitive (Subst ctx ctx') (<~>) where + transitive prf1 prf2 = MkEquivalence (\i => transitive (prf1.equiv i) (prf2.equiv i)) + +export +Equivalence (Subst ctx ctx') (<~>) where + +export +Preorder (Subst ctx ctx') (<~>) where + +namespace Subst + export + Base : + {0 thin1, thin2 : ctx `Thins` ctx'} -> + thin1 <~> thin2 -> + Base thin1 <~> Base thin2 + Base prf = MkEquivalence (\i => varCong (prf.equiv i)) + + export + (:<) : + {0 sub1, sub2 : Subst ctx ctx'} -> + {0 t, u : Term ty ctx'} -> + sub1 <~> sub2 -> + t <~> u -> + sub1 :< t <~> sub2 :< u + prf1 :< prf2 = + MkEquivalence (\i => case i of Here => prf2; There i => prf1.equiv i) + +-- Operations ------------------------------------------------------------------ + +||| Shifts a substitution under a binder. +export +shift : Subst ctx ctx' -> Subst ctx (ctx' :< ty) +shift (Base thin) = Base (Drop thin) +shift (sub :< t) = shift sub :< shift t + +||| Lifts a substitution under a binder. +export +lift : Subst ctx ctx' -> Subst (ctx :< ty) (ctx' :< ty) +lift sub = shift sub :< Var Here + +||| Limits the domain of a substitution +export +(.) : Subst ctx' ctx'' -> ctx `Thins` ctx' -> Subst ctx ctx'' +Base thin' . thin = Base (thin' . thin) +(sub :< t) . Id = sub :< t +(sub :< t) . Empty = Base Empty +(sub :< t) . Drop thin = sub . thin +(sub :< t) . Keep thin = sub . thin :< t + +--- Properties + +export +shiftIndex : + (sub : Subst ctx ctx') -> + (i : Elem ty ctx) -> + shift (index sub i) <~> index (shift sub) i +shiftIndex (Base thin) i = CalcWith $ + |~ shift (Var $ index thin i) + <~ Var (There $ index thin i) ...(shiftVar (index thin i)) + <~ Var (index (Drop thin) i) ..<(varCong $ indexDrop thin i) +shiftIndex (sub :< v) Here = reflexive +shiftIndex (sub :< v) (There i) = shiftIndex sub i + +export +shiftCong : {0 sub1, sub2 : Subst ctx' ctx''} -> sub1 <~> sub2 -> shift sub1 <~> shift sub2 +shiftCong prf = irrelevantEquiv $ MkEquivalence (\i => + CalcWith $ + |~ index (shift sub1) i + <~ shift (index sub1 i) ..<(shiftIndex sub1 i) + <~ shift (index sub2 i) ...(shiftCong (prf.equiv i)) + <~ index (shift sub2) i ...(shiftIndex sub2 i)) + +export +liftCong : {0 sub1, sub2 : Subst ctx' ctx''} -> sub1 <~> sub2 -> lift sub1 <~> lift sub2 +liftCong prf = shiftCong prf :< (irrelevantEquiv $ reflexive) + +export +indexHomo : + (sub : Subst ctx' ctx'') -> + (thin : ctx `Thins` ctx') -> + (i : Elem ty ctx) -> + index sub (index thin i) = index (sub . thin) i +indexHomo (Base thin') thin i = cong Var (indexHomo thin' thin i) +indexHomo (sub :< v) Id i = cong (index (sub :< v)) $ indexId i +indexHomo (sub :< v) (Drop thin) i = Calc $ + |~ index (sub :< v) (index (Drop thin) i) + ~~ index (sub :< v) (There (index thin i)) ...(cong (index (sub :< v)) $ indexDrop thin i) + ~~ index sub (index thin i) ...(Refl) + ~~ index (sub . thin) i ...(indexHomo sub thin i) +indexHomo (sub :< v) (Keep thin) Here = Calc $ + |~ index (sub :< v) (index (Keep thin) Here) + ~~ index (sub :< v) Here ...(cong (index (sub :< v)) $ indexKeepHere thin) + ~~ v ...(Refl) +indexHomo (sub :< v) (Keep thin) (There i) = Calc $ + |~ index (sub :< v) (index (Keep thin) (There i)) + ~~ index (sub :< v) (There (index thin i)) ...(cong (index (sub :< v)) $ indexKeepThere thin i) + ~~ index sub (index thin i) ...(Refl) + ~~ index (sub . thin) i ...(indexHomo sub thin i) + +export +compCong : + {0 sub1, sub2 : Subst ctx' ctx''} -> + {0 thin1, thin2 : ctx `Thins` ctx'} -> + sub1 <~> sub2 -> + thin1 <~> thin2 -> + (sub1 . thin1) <~> (sub2 . thin2) +compCong prf1 prf2 = irrelevantEquiv $ MkEquivalence (\i => CalcWith $ + |~ index (sub1 . thin1) i + ~~ index sub1 (index thin1 i) ..<(indexHomo sub1 thin1 i) + <~ index sub2 (index thin1 i) ...(prf1.equiv (index thin1 i)) + ~~ index sub2 (index thin2 i) ...(cong (index sub2) $ prf2.equiv i) + ~~ index (sub2 . thin2) i ...(indexHomo sub2 thin2 i)) + +-- Substitution Operation ------------------------------------------------------ + +fullSubst : FullTerm ty ctx -> Subst ctx ctx' -> Term ty ctx' +fullSubst Var sub = index sub Here +fullSubst (Const t) sub = Const (fullSubst t sub) +fullSubst (Abs t) sub = Abs (fullSubst t $ lift sub) +fullSubst (App (MakePair (t `Over` thin1) (u `Over` thin2) _)) sub = + App (fullSubst t $ sub . thin1) (fullSubst u $ sub . thin2) +fullSubst Zero sub = Zero +fullSubst (Suc t) sub = Suc (fullSubst t sub) +fullSubst + (Rec (MakePair + (t `Over` thin1) + (MakePair (u `Over` thin2) (v `Over` thin3) _ `Over` thin') + _)) + sub = + let sub' = sub . thin' in + Rec + (fullSubst t $ sub . thin1) + (fullSubst u $ sub' . thin2) + (fullSubst v $ sub' . thin3) + +||| Applies a substitution to a term. +export +subst : Term ty ctx -> Subst ctx ctx' -> Term ty ctx' +subst (t `Over` thin) sub = fullSubst t (sub . thin) + +--- Properties + +fullSubstCong : + (t : FullTerm ty ctx) -> + {0 sub1, sub2 : Subst ctx ctx'} -> + sub1 <~> sub2 -> + fullSubst t sub1 <~> fullSubst t sub2 +fullSubstCong Var prf = prf.equiv Here +fullSubstCong (Const t) prf = constCong (fullSubstCong t prf) +fullSubstCong (Abs t) prf = absCong (fullSubstCong t $ liftCong prf) +fullSubstCong (App (MakePair (t `Over` thin1) (u `Over` thin2) _)) prf = + appCong + (fullSubstCong t $ compCong prf reflexive) + (fullSubstCong u $ compCong prf reflexive) +fullSubstCong Zero prf = irrelevantEquiv $ reflexive +fullSubstCong (Suc t) prf = sucCong (fullSubstCong t prf) +fullSubstCong + (Rec (MakePair + (t `Over` thin1) + (MakePair (u `Over` thin2) (v `Over` thin3) _ `Over` thin') + _)) + prf = + let prf' = compCong prf reflexive in + recCong + (fullSubstCong t $ compCong prf reflexive) + (fullSubstCong u $ compCong prf' reflexive) + (fullSubstCong v $ compCong prf' reflexive) + +export +substCong : + {0 t, u : Term ty ctx} -> + {0 sub1, sub2 : Subst ctx ctx'} -> + t <~> u -> + sub1 <~> sub2 -> + subst t sub1 <~> subst u sub2 +substCong (UpToThin prf1) prf2 = irrelevantEquiv $ fullSubstCong _ (compCong prf2 prf1) + +export +substBase : + (t : Term ty ctx) -> + (thin : ctx `Thins` ctx') -> + subst t (Base thin) <~> wkn t thin + +export +substHomo : + (t : Term ty ctx) -> + (sub1 : Subst ctx ctx') -> + (sub2 : Subst ctx' ctx'') -> + subst (subst t sub1) sub2 <~> subst t ?d |