{-# OPTIONS --safe --without-K #-} module IK.Term.Properties where -- Welcome to the hell of mind-numbing syntactic lemmas. -- No good ever comes from proving these lemmas, but no -- good can happen without proving them. open import Data.Product using (Σ ; ∃ ; _×_ ; _,_ ; proj₁ ; proj₂) open import Relation.Binary.PropositionalEquality using (_≡_ ; refl ; sym ; trans ; cong ; cong₂ ; subst ; subst-application) open import PEUtil open import IK.Term.Base open import IK.Term.Reduction -------------------- -- Substitution laws -------------------- -- NOTE: these are only the laws that follow directly from the structure of substitutions coh-trimSub-wkVar : (x : Var Γ a) (s : Sub Δ' Δ) (w : Γ ⊆ Δ) → substVar (trimSub w s) x ≡ substVar s (wkVar w x) coh-trimSub-wkVar zero (s `, x) (drop w) = coh-trimSub-wkVar zero s w coh-trimSub-wkVar zero (s `, x) (keep w) = refl coh-trimSub-wkVar (succ x) (s `, x₁) (drop w) = coh-trimSub-wkVar (succ x) s w coh-trimSub-wkVar (succ x) (s `, x₁) (keep w) = coh-trimSub-wkVar x s w -- `trimSub` preserves the identity trimSubPresId : (s : Sub Δ Γ) → trimSub idWk s ≡ s trimSubPresId [] = refl trimSubPresId (s `, x) = cong (_`, _) (trimSubPresId s) trimSubPresId (lock s x) = cong₂ lock (trimSubPresId s) refl -- naturality of substVar nat-substVar : (x : Var Γ a) (s : Sub Δ Γ) (w : Δ ⊆ Δ') → substVar (wkSub w s) x ≡ wkTm w (substVar s x) nat-substVar zero (s `, t) w = refl nat-substVar (succ x) (s `, t) w = nat-substVar x s w -- naturality of trimSub nat-trimSub : (s : Sub Γ Δ) (w : Δ' ⊆ Δ) (w' : Γ ⊆ Γ') → wkSub w' (trimSub w s) ≡ trimSub w (wkSub w' s) nat-trimSub [] base w' = refl nat-trimSub (s `, t) (drop w) w' = nat-trimSub s w w' nat-trimSub (s `, t) (keep w) w' = cong (_`, wkTm w' t) (nat-trimSub s w w') nat-trimSub (lock s x) (keep# w) w' = cong₂ lock (nat-trimSub s w _) refl -- `trimSub` on the identity substitution embeds the weakening trimSubId : (w : Γ ⊆ Δ) → trimSub w idₛ ≡ embWk w trimSubId base = refl trimSubId (drop w) = trans (sym (nat-trimSub idₛ w fresh)) (cong (wkSub fresh) (trimSubId w)) trimSubId (keep w) = cong (_`, var zero) (trans (sym (nat-trimSub idₛ w fresh)) (cong (wkSub fresh) (trimSubId w))) trimSubId (keep# w) = cong₂ lock (trimSubId w) refl --------------- -- Functor laws --------------- -- Standard, standard, standard, oh wait... wkTmPresId : (t : Tm Γ a) → wkTm idWk t ≡ t wkTmPresId (var v) = cong var (wkVarPresId v) wkTmPresId (lam t) = cong lam (wkTmPresId t) wkTmPresId (app t u) = cong₂ app (wkTmPresId t) (wkTmPresId u) wkTmPresId (box t) = cong box (wkTmPresId t) wkTmPresId (unbox t e) with ←#IsPre# e | #→IsPost# e wkTmPresId (unbox t e) | refl | refl = cong₂ unbox (trans (cong₂ wkTm (sliceLeftId e) refl) (wkTmPresId t)) (wkLFExtPresId e) wkSubPresId : (s : Sub Γ Δ) → wkSub idWk s ≡ s wkSubPresId [] = refl wkSubPresId (s `, t) = cong₂ _`,_ (wkSubPresId s) (wkTmPresId t) wkSubPresId (lock s e) with ←#IsPre# e | #→IsPost# e ... | refl | refl = cong₂ lock (trans (cong₂ wkSub (sliceLeftId e) refl) (wkSubPresId s)) (wkLFExtPresId e) -- weakening of terms (a functor map) preserves weakening composition wkTmPres∙ : (w : Γ ⊆ Γ') (w' : Γ' ⊆ Δ) (t : Tm Γ a) → wkTm w' (wkTm w t) ≡ wkTm (w ∙ w') t wkTmPres∙ w w' (var v) = cong var (wkVarPres∙ w w' v) wkTmPres∙ w w' (lam t) = cong lam (wkTmPres∙ (keep w) (keep w') t) wkTmPres∙ w w' (app t u) = cong₂ app (wkTmPres∙ w w' t) (wkTmPres∙ w w' u) wkTmPres∙ w w' (box t) = cong box (wkTmPres∙ (keep# w) (keep# w') t) wkTmPres∙ w w' (unbox t e) = cong₂ unbox (trans (wkTmPres∙ _ _ _) (cong₂ wkTm (sliceLeftPres∙ w w' e) refl)) (wkLFExtPres∙ w w' e) -- weakening of substitutions preserves weakening compisition wkSubPres∙ : (w : Γ ⊆ Γ') (w' : Γ' ⊆ Δ) (s : Sub Γ ΓR) → wkSub w' (wkSub w s) ≡ wkSub (w ∙ w') s wkSubPres∙ w w' [] = refl wkSubPres∙ w w' (s `, t) = cong₂ _`,_ (wkSubPres∙ w w' s) (wkTmPres∙ w w' t) wkSubPres∙ w w' (lock s e) = cong₂ lock (trans (wkSubPres∙ _ _ s) (cong₂ wkSub (sliceLeftPres∙ w w' e) refl)) (wkLFExtPres∙ w w' e) private wkSubFreshLemma : {s : Sub Δ Γ} {w : Δ ⊆ Δ'} → wkSub fresh[ a ] (wkSub w s) ≡ wkSub (keep w) (dropₛ s) wkSubFreshLemma {s = s} {w} = trans (wkSubPres∙ w fresh s) (trans (cong₂ wkSub (cong drop (rightIdWk _)) refl ) (sym (trans (wkSubPres∙ _ _ _) (cong₂ wkSub (cong drop (leftIdWk _)) refl)))) nat-subsTm : (t : Tm Γ a) (s : Sub Δ Γ) (w : Δ ⊆ Δ') → substTm (wkSub w s) t ≡ wkTm w (substTm s t) nat-subsTm (var x) s w = nat-substVar x s w nat-subsTm (lam {Γ} {a} t) s w = cong lam (trans (cong (λ s → substTm (s `, var zero) t) wkSubFreshLemma) (nat-subsTm t (keepₛ s) (keep w))) nat-subsTm (app t u) s w = cong₂ app (nat-subsTm t s w) (nat-subsTm u s w) nat-subsTm (box t) s w = cong box (nat-subsTm t (lock s nil) (keep# w)) nat-subsTm (unbox t nil) (lock s x) w = cong₂ unbox (nat-subsTm t s _) refl nat-subsTm (unbox t (ext x)) (s `, _) w = nat-subsTm (unbox t x) s w -- weakening a substitution composition is the same as weakening the first sub -- (s ∙ₛ s') ₛ∙ₑ w ≡ s ∙ₛ (s' ₛ∙ₑ w) coh-wkSub-∙ₛ : {Δ'' : Ctx} (s : Sub Δ Γ) (s' : Sub Δ' Δ) (w : Δ' ⊆ Δ'') → wkSub w (s ∙ₛ s') ≡ s ∙ₛ (wkSub w s') coh-wkSub-∙ₛ [] s' w = refl coh-wkSub-∙ₛ (s `, x) s' w = cong₂ _`,_ (coh-wkSub-∙ₛ s s' w) (sym (nat-subsTm x s' w)) coh-wkSub-∙ₛ (lock s nil) (lock s' x) w = cong₂ lock (coh-wkSub-∙ₛ s s' _) refl coh-wkSub-∙ₛ (lock s (ext x)) (s' `, x₁) w = coh-wkSub-∙ₛ (lock s x) s' w -- applying a trimmed substitution is the same as weakening and substituting coh-trimSub-wkTm : (t : Tm Γ a) (s : Sub Δ' Δ) (w : Γ ⊆ Δ) → substTm (trimSub w s) t ≡ substTm s (wkTm w t) coh-trimSub-wkTm (var x) s w = coh-trimSub-wkVar x s w coh-trimSub-wkTm (lam t) s w = cong lam (trans (cong (λ p → substTm (p `, var zero) t) (nat-trimSub s w fresh)) (coh-trimSub-wkTm t (keepₛ s) (keep w))) coh-trimSub-wkTm (app t u) s w = cong₂ app (coh-trimSub-wkTm t s w) (coh-trimSub-wkTm u s w) coh-trimSub-wkTm (box t) s w = cong box (coh-trimSub-wkTm t (lock s nil) (keep# w)) coh-trimSub-wkTm (unbox t nil) (s `, x) (drop w) = coh-trimSub-wkTm (unbox t nil) s w coh-trimSub-wkTm (unbox t (ext e)) (s `, x) (drop w) = coh-trimSub-wkTm (unbox t (ext e)) s w coh-trimSub-wkTm (unbox t (ext e)) (s `, x) (keep w) = coh-trimSub-wkTm (unbox t e) s w coh-trimSub-wkTm (unbox t nil) (lock s x) (keep# w) = cong₂ unbox (coh-trimSub-wkTm t s w) refl -- trimming the first sub in a composition is the same as weakening the second -- s ∙ₛ (w ₑ∙ₛ s') ≡ (s ₛ∙ₑ w) ∙ₛ s' coh-trimSub-wkSub : {Δ₁ : Ctx} (s : Sub Δ Γ) (s' : Sub Δ₁ Δ') (w : Δ ⊆ Δ') → s ∙ₛ (trimSub w s') ≡ (wkSub w s) ∙ₛ s' coh-trimSub-wkSub [] s' w = refl coh-trimSub-wkSub (s `, x) s' w = cong₂ _`,_ (coh-trimSub-wkSub s s' w) (coh-trimSub-wkTm x s' w) coh-trimSub-wkSub (lock s nil) (s' `, x) (drop w) = coh-trimSub-wkSub (lock s nil) s' w coh-trimSub-wkSub (lock s nil) (lock s' x) (keep# w) = cong₂ lock (coh-trimSub-wkSub s s' w) refl coh-trimSub-wkSub (lock s (ext e)) (s' `, x₁) (drop w) = coh-trimSub-wkSub (lock s (ext e)) s' w coh-trimSub-wkSub (lock s (ext x)) (s' `, x₁) (keep w) = coh-trimSub-wkSub (lock s x) s' w -- parallel substitution (substVar) preserves substitution composition substVarPres∙ : (s : Sub Γ' Γ) (s' : Sub Δ Γ') (x : Var Γ a) → substTm s' (substVar s x) ≡ substVar (s ∙ₛ s') x substVarPres∙ (s `, x) s' zero = refl substVarPres∙ (s `, x) s' (succ x₁) = substVarPres∙ s s' x₁ private dropKeepLemma : (s' : Sub Δ' Δ) (s : Sub Γ Δ') → dropₛ (s' ∙ₛ s) ≡ dropₛ {a = a} s' ∙ₛ keepₛ s dropKeepLemma s' s = trans (coh-wkSub-∙ₛ s' s fresh) (trans ((cong (s' ∙ₛ_) (sym (trimSubPresId (dropₛ s))))) (coh-trimSub-wkSub s' (keepₛ s) fresh)) substVarPresId : (x : Var Γ a) → substVar idₛ x ≡ var x substVarPresId zero = refl substVarPresId (succ x) = trans (nat-substVar x idₛ fresh) (trans (cong (wkTm fresh) (substVarPresId x)) (cong var (wkIncr x))) module _ {e : LFExt Δ (Γ #) ΓR} {e' : LFExt Δ (Γ' #) ΓR'} where cong-unbox≡ : (Γ≡Γ' : Γ ≡ Γ') → (t≡t' : subst (λ Γ → Tm Γ (□ a)) Γ≡Γ' t ≡ t') → unbox t e ≡ unbox t' e' cong-unbox≡ Γ≡Γ' t≡t' = idcong₄ unbox Γ≡Γ' (extRUniq′ (cong _# Γ≡Γ') e e') t≡t' (ExtIsProp _ _) cong-unbox≡1 : (Γ≡Γ' : Γ ≡ Γ') → (t≡t' : subst (λ Γ → Tm Γ (□ a)) Γ≡Γ' t ≡ t') → unbox t e ≡ unbox t' e' cong-unbox≡1 = cong-unbox≡ cong-unbox≡2 : unbox t e ≡ unbox t e' cong-unbox≡2 = cong-unbox≡ refl refl module _ {Γ : Ctx} {a : Ty} where unbox-natural : (t : Tm Γ (□ a)) → (e : LFExt Δ (Γ #) ΓR) → (w : LFExt Δ' Δ ΔR) → unbox t (e ∙Ext w) ≡ wkTm (LFExtToWk w) (unbox t e) unbox-natural t e w with ←#IsPre# e | #→IsPost# e unbox-natural t e w | refl | refl = cong-unbox≡ (←#IsPre# w) (trans (cong˘ (subst (λ Γ → Tm Γ (□ a)) (←#IsPre# w)) (wkTmPresId t)) (trans (subst-application′ (λ w → wkTm w t) (←#IsPre# w)) (cong˘ (λ w → wkTm w t) (sliceLeftDrop e w)))) unbox-universal : (t : Tm Γ (□ a)) → (e : LFExt Δ (Γ #) ΓR) → unbox t e ≡ wkTm (LFExtToWk e) (unbox t new) unbox-universal t e = trans cong-unbox≡2 (unbox-natural t new e) substTmPresId : (t : Tm Γ a) → substTm idₛ t ≡ t substTmPresId (var x) = substVarPresId x substTmPresId (lam t) = cong lam (substTmPresId t) substTmPresId (app t u) = cong₂ app (substTmPresId t) (substTmPresId u) substTmPresId (box t) = cong box (substTmPresId t) substTmPresId (unbox t nil) = cong₂ unbox (substTmPresId t) refl substTmPresId {Γ = Γ `, a} (unbox t (ext e)) with ←#IsPre# e | #→IsPost# e | substTmPresId (unbox t e) ... | refl | refl | rec = trans (nat-subsTm (unbox t e) idₛ fresh) (trans˘ (cong (wkTm fresh) rec) (unbox-natural t e (ext nil))) -- NOTE: the `rec` here is a hack required for/after the 2.6.1 update -- c.f. "Termination checking" in http://hackage.haskell.org/package/Agda-2.6.1/changelog -- parallel substitution (substTm) preserves substitution composition substTmPres∙ : (s : Sub Γ' Γ) (s' : Sub Δ Γ') (t : Tm Γ a) → substTm s' (substTm s t) ≡ substTm (s ∙ₛ s') t substTmPres∙ s s' (var x) = substVarPres∙ s s' x substTmPres∙ s s' (lam t) = cong lam (trans (substTmPres∙ _ _ t) (cong ((λ s → substTm (s `, var zero) t)) (sym (dropKeepLemma s s')))) substTmPres∙ s s' (app t u) = cong₂ app (substTmPres∙ s s' t) (substTmPres∙ s s' u) substTmPres∙ s s' (box t) = cong box (substTmPres∙ (lock s nil) (lock s' nil) t) substTmPres∙ (lock s nil) (lock s' nil) (unbox t nil) = cong₂ unbox (substTmPres∙ s s' t) refl substTmPres∙ (lock s nil) (lock s' (ext x)) (unbox t nil) = cong₂ unbox (substTmPres∙ s s' t) refl substTmPres∙ (lock s (ext e)) (s' `, _) (unbox t nil) = substTmPres∙ (lock s e) s' (unbox t nil) substTmPres∙ (lock s nil) (lock s' _) (unbox t nil) = cong₂ unbox (substTmPres∙ s s' t) refl substTmPres∙ (s `, e) s' (unbox t (ext e')) = substTmPres∙ s s' (unbox t e') rightIdSub : (s : Sub Γ Γ') → s ∙ₛ idₛ ≡ s rightIdSub [] = refl rightIdSub (s `, t) = cong₂ _`,_ (rightIdSub s) (substTmPresId t) rightIdSub (lock s nil) = cong₂ lock (rightIdSub s) refl rightIdSub (lock s (ext e)) with ←#IsPre# e | #→IsPost# e ... | refl | refl = trans (sym (coh-wkSub-∙ₛ (lock s e) _ _)) (trans (cong (wkSub fresh) (rightIdSub (lock s e))) (trans (cong₂ lock (cong₂ wkSub (sliceLeftId e) refl) (cong ext (wkLFExtPresId e))) (cong₂ lock (wkSubPresId s) refl))) -- substitution composition is associative assocSub : {Γ1 Γ2 Γ3 Γ4 : Ctx} → (s3 : Sub Γ3 Γ4) (s2 : Sub Γ2 Γ3) → (s1 : Sub Γ1 Γ2) → (s3 ∙ₛ s2) ∙ₛ s1 ≡ s3 ∙ₛ (s2 ∙ₛ s1) assocSub [] s2 s1 = refl assocSub (s3 `, t) s2 s1 = cong₂ _`,_ (assocSub s3 s2 s1) (substTmPres∙ s2 s1 t) assocSub (lock s3 nil) (lock s2 nil) (lock s1 e) = cong (λ p → lock p e) (assocSub s3 s2 s1) assocSub (lock s3 nil) (lock s2 (ext e)) (s1 `, _) = assocSub (lock s3 nil) (lock s2 e) s1 assocSub (lock s3 (ext e)) (s2 `, _) s1 = assocSub (lock s3 e) s2 s1 private -- just a helper to reduce redundancy, nothing too interesting auxLemma : (w : Γ ⊆ Δ) → wkSub (drop[ a ] (w ∙ idWk)) idₛ ≡ dropₛ (embWk w) wkSubId : (w : Γ ⊆ Δ) → wkSub w idₛ ≡ embWk w auxLemma w = (trans (sym (wkSubPres∙ w fresh idₛ)) (cong (wkSub fresh) (wkSubId w))) wkSubId base = refl wkSubId (drop w) = trans (cong (λ w' → wkSub (drop w') idₛ) (sym (rightIdWk w))) (auxLemma w) wkSubId (keep w) = cong (_`, var zero) (trans (wkSubPres∙ fresh (keep w) idₛ) (trans (cong₂ wkSub (cong drop (trans (leftIdWk _) (sym (rightIdWk _)))) refl) (auxLemma w))) wkSubId (keep# w) = cong₂ lock (wkSubId w) refl -- Outcast lemmas keepFreshLemma : {w : Γ ⊆ Γ'} {t : Tm Γ a} → wkTm fresh[ b ] (wkTm w t) ≡ wkTm (keep w) (wkTm fresh t) keepFreshLemma = trans (wkTmPres∙ _ _ _) (sym (trans (wkTmPres∙ _ _ _) (cong₂ wkTm (cong drop (trans (leftIdWk _) (sym (rightIdWk _)))) refl))) sliceCompLemma : (w : Γ ⊆ Δ) (e : LFExt Γ (ΓL #) ΓR) (t : Tm (ΓL #) a) → wkTm (LFExtToWk (wkLFExt e w)) (wkTm (keep# (sliceLeft e w)) t) ≡ wkTm w (wkTm (LFExtToWk e) t) sliceCompLemma w e t = (trans (wkTmPres∙ _ _ _) (sym (trans (wkTmPres∙ _ _ _) (cong₂ wkTm (slicingLemma w e) refl)))) beta-wk-lemma : (w : Γ ⊆ Δ) (u : Tm Γ a) (t : Tm (Γ `, a) b) → substTm (idₛ `, wkTm w u) (wkTm (keep w) t) ≡ wkTm w (substTm (idₛ `, u) t) beta-wk-lemma w u t = trans (sym (coh-trimSub-wkTm t _ (keep w))) (sym (trans (sym (nat-subsTm t _ _)) (cong (λ p → substTm (p `, wkTm w u) t) (sym (trans (trimSubId w) (sym (wkSubId w))))))) ----------------------------------- --- Reduction and conversion lemmas ----------------------------------- wkTmPres⟶ : {t t' : Tm Γ a} → (w : Γ ⊆ Δ) → t ⟶ t' → wkTm w t ⟶ wkTm w t' wkTmPres⟶ w (red-fun {t = t} {u = u}) = step-≡ red-fun (beta-wk-lemma w u t) wkTmPres⟶ w exp-fun = step-≡ exp-fun (cong lam (cong₂ app keepFreshLemma refl)) wkTmPres⟶ w (red-box {e = e}) = step-≡ red-box (sliceCompLemma w e _) wkTmPres⟶ w exp-box = exp-box wkTmPres⟶ w (cong-lam r) = cong-lam (wkTmPres⟶ (keep w) r) wkTmPres⟶ w (cong-box r) = cong-box (wkTmPres⟶ (keep# w) r) wkTmPres⟶ w (cong-unbox r) = cong-unbox (wkTmPres⟶ (sliceLeft _ w) r) wkTmPres⟶ w (cong-app1 r) = cong-app1 (wkTmPres⟶ w r) wkTmPres⟶ w (cong-app2 r) = cong-app2 (wkTmPres⟶ w r) wkTmPres⟶* : {t t' : Tm Γ a} → (w : Γ ⊆ Δ) → t ⟶* t' → wkTm w t ⟶* wkTm w t' wkTmPres⟶* w = cong-⟶-to-cong-⟶* (wkTmPres⟶ w)
Generated from commit 2fd14c996b195ef101dff8919e837907ca0a08aa.