{-# OPTIONS --without-K --safe #-} module STLCSubst.Statics.Properties.Ops where open import Level using (0ℓ; _⊔_) renaming (suc to lsuc) open import Relation.Binary using (Rel; Setoid; IsEquivalence) open import Relation.Binary.PropositionalEquality hiding ([_]) open import Relation.Binary.PropositionalEquality using (_≗_) public import Data.Nat.Properties as ℕₚ import Relation.Binary.Reasoning.Setoid as SR open import Lib open import STLCSubst.Statics.Definitions record AlgLemmas {i} (A : Set i) : Set (lsuc i) where infix 4 _≈_ field {{has-id}} : HasIdentity A {{composable}} : Composable A {{head-wk}} : HeadWeaken A _≈_ : Rel A 0ℓ ≈-equiv : IsEquivalence _≈_ left-id : ∀ a → id ∙ a ≈ a right-id : ∀ a → a ∙ id ≈ a assoc : ∀ a b c → (a ∙ b) ∙ c ≈ a ∙ (b ∙ c) ∙-cong : ∀ a b c d → a ≈ b → c ≈ d → a ∙ c ≈ b ∙ d q-id : q id ≈ id q-cong : ∀ {a b} → a ≈ b → q a ≈ q b q-∙-dist : ∀ a b → q a ∙ q b ≈ q (a ∙ b) ≈-setoid : Setoid _ _ ≈-setoid = record { Carrier = _ ; _≈_ = _≈_ ; isEquivalence = ≈-equiv } module ≈ = Setoid ≈-setoid module ≈-Reasoning = SR ≈-setoid repeat-q-∙-dist : ∀ n a b → repeat q n a ∙ repeat q n b ≈ repeat q n (a ∙ b) repeat-q-∙-dist zero a b = ≈.refl repeat-q-∙-dist (suc n) a b = ≈.trans (q-∙-dist (repeat q n a) (repeat q n b)) (q-cong (repeat-q-∙-dist n a b)) repeat-q-id : ∀ n → repeat q n id ≈ id repeat-q-id zero = ≈.refl repeat-q-id (suc n) = ≈.trans (q-cong (repeat-q-id n)) q-id open AlgLemmas {{...}} hiding (_≈_; has-id; composable; head-wk) public --------------------------------------- -- properties of weakenings module ≗ {a b} {A : Set a} {B : Set b} = Setoid (A →-setoid B) wk-q-cong : ϕ ≗ ψ → q ϕ ≗ q ψ wk-q-cong eq zero = refl wk-q-cong eq (suc x) = cong suc (eq x) wk-transp : (t : Exp) → ϕ ≗ ψ → t [ ϕ ] ≡ t [ ψ ] wk-transp (v x) eq = cong v (eq x) wk-transp ze eq = refl wk-transp (su t) eq = cong su (wk-transp t eq) wk-transp (rec T u s t) eq rewrite wk-transp u eq | wk-transp s (wk-q-cong (wk-q-cong eq)) | wk-transp t eq = refl wk-transp (Λ t) eq = cong Λ (wk-transp t (wk-q-cong eq)) wk-transp (t $ s) eq = cong₂ _$_ (wk-transp t eq) (wk-transp s eq) wk-q-∙-dist : (ϕ ψ : Wk) → q ϕ ∙ q ψ ≗ q (ϕ ∙ ψ) wk-q-∙-dist ϕ ψ zero = refl wk-q-∙-dist ϕ ψ (suc x) = refl wk-qq-∙-dist : (ϕ ψ : Wk) → q (q ϕ) ∙ q (q ψ) ≗ q (q (ϕ ∙ ψ)) wk-qq-∙-dist ϕ ψ = ≗.trans (wk-q-∙-dist (q ϕ) (q ψ)) (wk-q-cong (wk-q-∙-dist ϕ ψ)) wk-app-comb : (t : Exp) (ϕ ψ : Wk) → t [ ϕ ] [ ψ ] ≡ t [ ϕ ∙ ψ ] wk-app-comb (v x) ϕ ψ = refl wk-app-comb ze ϕ ψ = refl wk-app-comb (su t) ϕ ψ = cong su (wk-app-comb t ϕ ψ) wk-app-comb (rec T u s t) ϕ ψ rewrite wk-app-comb u ϕ ψ | trans (wk-app-comb s (q (q ϕ)) (q (q ψ))) (wk-transp s (wk-qq-∙-dist ϕ ψ)) | wk-app-comb t ϕ ψ = refl wk-app-comb (Λ t) ϕ ψ = cong Λ (trans (wk-app-comb t (q ϕ) (q ψ)) (wk-transp t (wk-q-∙-dist ϕ ψ))) wk-app-comb (t $ s) ϕ ψ = cong₂ _$_ (wk-app-comb t ϕ ψ) (wk-app-comb s ϕ ψ) wk-comp-q : (n : ℕ) (t : Exp) (ϕ : Wk) → t [ repeat q n ⇑ ] [ repeat q n (q ϕ) ] ≡ t [ repeat q n ϕ ] [ repeat q n ⇑ ] wk-comp-q n (v x) ϕ = cong v (lem n x) where lem : ∀ n x → repeat q n (q ϕ) (repeat q n ⇑ x) ≡ repeat q n ⇑ (repeat q n ϕ x) lem zero x = refl lem (suc n) zero = refl lem (suc n) (suc x) rewrite lem n x = refl wk-comp-q n ze ϕ = refl wk-comp-q n (su t) ϕ = cong su (wk-comp-q n t ϕ) wk-comp-q n (rec T u s t) ϕ rewrite wk-comp-q n u ϕ | wk-comp-q (2 + n) s ϕ | wk-comp-q n t ϕ = refl wk-comp-q n (Λ t) ϕ = cong Λ (wk-comp-q (1 + n) t ϕ) wk-comp-q n (t $ s) ϕ = cong₂ _$_ (wk-comp-q n t ϕ) (wk-comp-q n s ϕ) wk-suc : ∀ n x → wk (suc n) (suc x) ≡ suc (wk n x) wk-suc n x with n ≤? x | suc n ≤? suc x ... | yes p | yes p′ = refl ... | yes p | no ¬p′ = ⊥-elim (¬p′ (s≤s p)) ... | no ¬p | yes (s≤s p′) = ⊥-elim (¬p p′) ... | no ¬p | no ¬p′ = refl wk-repeat-q-eq : ∀ n → repeat q n ⇑ ≗ wk n wk-repeat-q-eq zero x = refl wk-repeat-q-eq (suc n) zero = refl wk-repeat-q-eq (suc n) (suc x) rewrite wk-repeat-q-eq n x | wk-suc n x = refl wk-repeat-q-gen : ∀ n m → repeat q n (wk m) ≗ wk (n + m) wk-repeat-q-gen zero m x = refl wk-repeat-q-gen (suc n) zero x rewrite ℕₚ.+-identityʳ n = wk-repeat-q-eq (suc n) x wk-repeat-q-gen (suc n) (suc m) zero = refl wk-repeat-q-gen (suc n) (suc m) (suc x) rewrite wk-repeat-q-gen n (suc m) x | wk-suc (n + suc m) x = refl wk-q-wk0 : (n : ℕ) (t : Exp) → t [ repeat q n ⇑ ] [ ⇑ ] ≡ t [ ⇑ ] [ repeat q (1 + n) ⇑ ] wk-q-wk0 n t = begin t [ repeat q n ⇑ ] [ ⇑ ] ≡⟨ cong (_[ ⇑ ]) (wk-transp t (wk-repeat-q-eq n)) ⟩ t [ wk n ] [ ⇑ ] ≡⟨ wk-app-comb t (wk n) ⇑ ⟩ t [ wk n ∙ ⇑ ] ≡⟨ wk-transp t lem ⟩ t [ ⇑ ∙ wk (1 + n) ] ≡⟨ sym (wk-app-comb t ⇑ (wk (1 + n))) ⟩ t [ ⇑ ] [ wk (1 + n) ] ≡⟨ sym (wk-transp (t [ ⇑ ]) (wk-repeat-q-eq (1 + n))) ⟩ t [ ⇑ ] [ repeat q (1 + n) ⇑ ] ∎ where open ≡-Reasoning lem : wk-compose (wk n) ⇑ ≗ wk-compose ⇑ (wk (suc n)) lem x rewrite wk-suc n x = refl wk-comp-q-equiv-gen : (n : ℕ) (t : Exp) (σ : Subst) → t [ repeat q n ⇑ ] [ repeat q n (q σ) ] ≡ t [ repeat q n σ ] [ repeat q n ⇑ ] wk-comp-q-equiv-gen n (v x) σ = lem n x where lem : ∀ n x → repeat q n (q σ) (repeat q n ⇑ x) ≡ (repeat q n σ x) [ repeat q n ⇑ ] lem zero x = refl lem (suc n) zero = refl lem (suc n) (suc x) rewrite lem n x = wk-q-wk0 n (repeat q n σ x) wk-comp-q-equiv-gen n ze σ = refl wk-comp-q-equiv-gen n (su t) σ = cong su (wk-comp-q-equiv-gen n t σ) wk-comp-q-equiv-gen n (rec T u s t) σ rewrite wk-comp-q-equiv-gen n u σ | wk-comp-q-equiv-gen (2 + n) s σ | wk-comp-q-equiv-gen n t σ = refl wk-comp-q-equiv-gen n (Λ t) σ = cong Λ (wk-comp-q-equiv-gen (1 + n) t σ) wk-comp-q-equiv-gen n (t $ s) σ = cong₂ _$_ (wk-comp-q-equiv-gen n t σ) (wk-comp-q-equiv-gen n s σ) wk-qid≈id : wk-q id ≗ id wk-qid≈id zero = refl wk-qid≈id (suc x) = refl wk-qqid≈id : wk-q (q id) ≗ id wk-qqid≈id = ≗.trans (wk-q-cong wk-qid≈id) wk-qid≈id wk-app-id : (t : Exp) → wk-app t id ≡ t wk-app-id (v x) = refl wk-app-id ze = refl wk-app-id (su t) = cong su (wk-app-id t) wk-app-id (rec T u s t) rewrite wk-app-id u | trans (wk-transp s wk-qqid≈id) (wk-app-id s) | wk-app-id t = refl wk-app-id (Λ t) = cong Λ (trans (wk-transp t wk-qid≈id) (wk-app-id t)) wk-app-id (t $ s) = cong₂ _$_ (wk-app-id t) (wk-app-id s) wk-∙-cong : (ϕ ϕ′ ψ ψ′ : Wk) → ϕ ≗ ϕ′ → ψ ≗ ψ′ → ϕ ∙ ψ ≗ ϕ′ ∙ ψ′ wk-∙-cong ϕ ϕ′ ψ ψ′ eq eq′ x rewrite eq x = eq′ _ --------------------------------------- -- properties of substitutions subst-qid≈id : q v ≗ id subst-qid≈id zero = refl subst-qid≈id (suc _) = refl subst-q-cong : σ ≗ τ → q σ ≗ q τ subst-q-cong eq zero = refl subst-q-cong eq (suc x) = cong (λ z → z [ ⇑ ]) (eq x) subst-qqid≈id : q (q v) ≗ id subst-qqid≈id = ≗.trans (subst-q-cong subst-qid≈id) subst-qid≈id q-alt : Subst → Subst q-alt σ = σ [ ⇑ ] ↦ v 0 conv-equiv-gen : (n : ℕ) (t : Exp) (ϕ : Wk) → t [ repeat q n (conv ϕ) ] ≡ t [ repeat q n ϕ ] conv-equiv-gen n (v x) ϕ = lem n x where lem : ∀ n x → repeat subst-q n (conv ϕ) x ≡ v (repeat wk-q n ϕ x) lem zero x = refl lem (suc n) zero = refl lem (suc n) (suc x) rewrite lem n x = refl conv-equiv-gen n ze ϕ = refl conv-equiv-gen n (su t) ϕ = cong su (conv-equiv-gen n t ϕ) conv-equiv-gen n (rec T u s t) ϕ rewrite conv-equiv-gen n u ϕ | conv-equiv-gen (2 + n) s ϕ | conv-equiv-gen n t ϕ = refl conv-equiv-gen n (Λ t) ϕ = cong Λ (conv-equiv-gen (1 + n) t ϕ) conv-equiv-gen n (t $ s) ϕ = cong₂ _$_ (conv-equiv-gen n t ϕ) (conv-equiv-gen n s ϕ) conv-equiv : (t : Exp) (ϕ : Wk) → t [ conv ϕ ] ≡ t [ ϕ ] conv-equiv = conv-equiv-gen 0 subst-q-equiv : (σ : Subst) → q σ ≗ q-alt σ subst-q-equiv σ zero = refl subst-q-equiv σ (suc x) = refl wk-drop-ext : (σ : Subst) (t : Exp) → conv ⇑ ∙ (σ ↦ t) ≗ σ wk-drop-ext _ _ _ = refl subst-q-∙-dist : (σ σ′ : Subst) → q σ ∙ q σ′ ≗ q (σ ∙ σ′) subst-q-∙-dist σ σ′ zero = refl subst-q-∙-dist σ σ′ (suc x) = begin σ x [ ⇑ ] [ q σ′ ] ≡⟨ wk-comp-q-equiv-gen 0 (σ x) σ′ ⟩ σ x [ σ′ ] [ ⇑ ] ∎ where open ≡-Reasoning subst-qq-∙-dist : (σ σ′ : Subst) → q (q σ) ∙ q (q σ′) ≗ q (q (σ ∙ σ′)) subst-qq-∙-dist σ σ′ = begin q (q σ) ∙ q (q σ′) ≈⟨ subst-q-∙-dist (q σ) (q σ′) ⟩ q (q σ ∙ q σ′) ≈⟨ subst-q-cong (subst-q-∙-dist σ σ′) ⟩ q (q (σ ∙ σ′)) ∎ where open SR (ℕ →-setoid Exp) subst-transp : (t : Exp) → σ ≗ τ → t [ σ ] ≡ t [ τ ] subst-transp (v x) eq = eq x subst-transp ze eq = refl subst-transp (su t) eq = cong su (subst-transp t eq) subst-transp (rec T u s t) eq rewrite subst-transp u eq | subst-transp s (subst-q-cong (subst-q-cong eq)) | subst-transp t eq = refl subst-transp (Λ t) eq = cong Λ (subst-transp t (subst-q-cong eq)) subst-transp (t $ s) eq = cong₂ _$_ (subst-transp t eq) (subst-transp s eq) subst-app-id : (t : Exp) → t [ v ] ≡ t subst-app-id (v _) = refl subst-app-id ze = refl subst-app-id (su t) = cong su (subst-app-id t) subst-app-id (rec T u s t) rewrite subst-app-id u | trans (subst-transp s subst-qqid≈id) (subst-app-id s) | subst-app-id t = refl subst-app-id (Λ t) = cong Λ (trans (subst-transp t subst-qid≈id) (subst-app-id t)) subst-app-id (t $ s) = cong₂ _$_ (subst-app-id t) (subst-app-id s) subst-app-comb : (t : Exp) (σ σ′ : Subst) → t [ σ ] [ σ′ ] ≡ t [ σ ∙ σ′ ] subst-app-comb (v x) σ σ′ = refl subst-app-comb ze σ σ′ = refl subst-app-comb (su t) σ σ′ = cong su (subst-app-comb t σ σ′) subst-app-comb (rec T u s t) σ σ′ rewrite subst-app-comb u σ σ′ | trans (subst-app-comb s (q (q σ)) (q (q σ′))) (subst-transp s (subst-qq-∙-dist σ σ′)) | subst-app-comb t σ σ′ = refl subst-app-comb (Λ t) σ σ′ = cong Λ (trans (subst-app-comb t (q σ) (q σ′)) (subst-transp t (subst-q-∙-dist σ σ′))) subst-app-comb (t $ s) σ σ′ = cong₂ _$_ (subst-app-comb t σ σ′) (subst-app-comb s σ σ′) subst-comp-assoc : ∀ (σ σ′ σ″ : Subst) → (σ ∙ σ′) ∙ σ″ ≗ σ ∙ (σ′ ∙ σ″) subst-comp-assoc σ σ′ σ″ x = subst-app-comb (σ x) σ′ σ″ subst-∙-cong : (σ σ′ τ τ′ : Subst) → σ ≗ σ′ → τ ≗ τ′ → σ ∙ τ ≗ σ′ ∙ τ′ subst-∙-cong σ σ′ τ τ′ eq eq′ x rewrite eq x = subst-transp (σ′ x) eq′ subst-ext-η : ∀ σ → σ ≗ conv ⇑ ∙ σ ↦ (v 0 [ σ ]) subst-ext-η σ zero = refl subst-ext-η σ (suc x) = refl subst-ext-cong : ∀ {σ σ′ : Subst} {t t′ : Exp} → σ ≗ σ′ → t ≡ t′ → σ ↦ t ≗ σ′ ↦ t′ subst-ext-cong eq refl zero = refl subst-ext-cong eq refl (suc x) = eq x --------------------------------------- -- instances instance Wk-AlgLemmas : AlgLemmas Wk Wk-AlgLemmas = record { _≈_ = _≗_ ; ≈-equiv = Setoid.isEquivalence (ℕ →-setoid ℕ) ; left-id = λ _ _ → refl ; right-id = λ _ _ → refl ; assoc = λ _ _ _ _ → refl ; ∙-cong = wk-∙-cong ; q-id = wk-qid≈id ; q-cong = wk-q-cong ; q-∙-dist = wk-q-∙-dist } Subst-AlgLemmas : AlgLemmas Subst Subst-AlgLemmas = record { _≈_ = _≗_ ; ≈-equiv = Setoid.isEquivalence (ℕ →-setoid Exp) ; left-id = λ _ _ → refl ; right-id = λ σ x → subst-app-id (σ x) ; assoc = subst-comp-assoc ; ∙-cong = subst-∙-cong ; q-id = subst-qid≈id ; q-cong = subst-q-cong ; q-∙-dist = subst-q-∙-dist } --------------------------------------- -- more properties conv-q : ∀ ϕ → conv (q ϕ) ≗ q (conv ϕ) conv-q _ zero = refl conv-q _ (suc _) = refl conv-∙ : ∀ ϕ ψ → conv (ϕ ∙ ψ) ≗ conv ϕ ∙ conv ψ conv-∙ _ _ _ = refl ext-lookup-v0 : (σ : Subst) (t : Exp) → v 0 [ σ ↦ t ] ≡ t ext-lookup-v0 _ _ = refl ext-lookup-v1 : (σ : Subst) (t : Exp) (n : ℕ) → v (suc n) [ σ ↦ t ] ≡ v n [ σ ] ext-lookup-v1 _ _ _ = refl ext-comp : (σ δ : Subst) (t : Exp) → σ ↦ t ∙ δ ≗ σ ∙ δ ↦ (t [ δ ]) ext-comp σ δ t zero = refl ext-comp σ δ t (suc x) = refl subst-wk-id : (σ : Subst) → σ [ id ] ≗ σ subst-wk-id σ x = wk-app-id (σ x) wk-app-cong : (ϕ : Wk) → σ ≗ τ → σ [ ϕ ] ≗ τ [ ϕ ] wk-app-cong ϕ eq x rewrite eq x = refl ext-wk : (σ : Subst) (t : Exp) (ϕ : Wk) → (σ ↦ t) [ ϕ ] ≗ σ [ ϕ ] ↦ (t [ ϕ ]) ext-wk σ t ϕ zero = refl ext-wk σ t ϕ (suc x) = refl conv-equiv-subst : (σ : Subst) (ϕ : Wk) → σ ∙ conv ϕ ≗ σ [ ϕ ] conv-equiv-subst σ ϕ x = conv-equiv (σ x) ϕ wk-app-subst : (t : Exp) (σ : Subst) (ϕ : Wk) → t [ σ ] [ ϕ ] ≡ t [ σ [ ϕ ] ] wk-app-subst t σ ϕ = trans (sym (conv-equiv (subst-app t σ) ϕ)) (trans (subst-app-comb t σ (conv ϕ)) (subst-transp t (conv-equiv-subst σ ϕ))) exp-wk-ext : (t : Exp) (σ : Subst) (s : Exp) → t [ ⇑ ] [ σ ↦ s ] ≡ t [ σ ] exp-wk-ext t σ s = trans (cong _[ σ ↦ s ] (sym (conv-equiv t ⇑))) (subst-app-comb t (conv ⇑) (σ ↦ s)) exp-wk-q : (t : Exp) (σ : Subst) → t [ ⇑ ] [ q σ ] ≡ t [ σ [ ⇑ ] ] exp-wk-q t σ = trans (cong _[ q σ ] (sym (conv-equiv t ⇑))) (subst-app-comb t (conv ⇑) (q σ)) exp-wk-q′ : (t : Exp) (σ : Subst) → t [ ⇑ ] [ q σ ] ≡ t [ σ ] [ ⇑ ] exp-wk-q′ t σ = trans (exp-wk-q t σ) (sym (wk-app-subst t σ ⇑)) id-wk-conv : (ϕ : Wk) → id [ ϕ ] ≡ conv ϕ id-wk-conv ϕ = refl wk-id-ext-equiv-gen : (n : ℕ) (t : Exp) (ts : List Exp) (ϕ : Wk) → t [ repeat q n (subst-exts id ts) ] [ repeat q n ϕ ] ≡ t [ repeat q (n + L.length ts) ϕ ] [ repeat q n (subst-exts id (L.map (_[ ϕ ]) ts)) ] wk-id-ext-equiv-gen n (v x) ts ϕ = helper n ts x where helper : ∀ n ts x → repeat q n (subst-exts id ts) x [ repeat q n ϕ ] ≡ repeat q n (subst-exts id (L.map (_[ ϕ ]) ts)) (repeat q (n + L.length ts) ϕ x) helper zero [] x = refl helper zero (t ∷ ts) zero = refl helper zero (t ∷ ts) (suc x) = helper zero ts x helper (suc n) ts zero = refl helper (suc n) ts (suc x) = begin (repeat q n (subst-exts id ts) [ ⇑ ]) x [ repeat q (1 + n) ϕ ] ≡⟨ wk-comp-q 0 (repeat subst-q n (subst-exts id ts) x) (repeat q n ϕ) ⟩ repeat q n (subst-exts id ts) x [ repeat q n ϕ ] [ ⇑ ] ≡⟨ cong (_[ ⇑ ]) (helper n ts x) ⟩ (repeat q n (subst-exts id (L.map (_[ ϕ ]) ts)) [ ⇑ ]) (repeat q (n + L.length ts) ϕ x) ∎ where open ≡-Reasoning wk-id-ext-equiv-gen n ze ts ϕ = refl wk-id-ext-equiv-gen n (su t) ts ϕ = cong su (wk-id-ext-equiv-gen n t ts ϕ) wk-id-ext-equiv-gen n (rec T s r t) ts ϕ rewrite wk-id-ext-equiv-gen n s ts ϕ | wk-id-ext-equiv-gen (2 + n) r ts ϕ | wk-id-ext-equiv-gen n t ts ϕ = refl wk-id-ext-equiv-gen n (Λ t) ts ϕ = cong Λ (wk-id-ext-equiv-gen (1 + n) t ts ϕ) wk-id-ext-equiv-gen n (t $ s) ts ϕ = cong₂ _$_ (wk-id-ext-equiv-gen n t ts ϕ) (wk-id-ext-equiv-gen n s ts ϕ) wk-id-ext-equiv : (t : Exp) (ts : List Exp) (ϕ : Wk) → t [ subst-exts id ts ] [ ϕ ] ≡ t [ repeat q (L.length ts) ϕ ] [ subst-exts id (L.map (_[ ϕ ]) ts) ] wk-id-ext-equiv = wk-id-ext-equiv-gen 0 wk-id-ext₁ : (t s : Exp) (ϕ : Wk) → t [ id ↦ s ] [ ϕ ] ≡ t [ q ϕ ] [ id ↦ (s [ ϕ ]) ] wk-id-ext₁ t s = wk-id-ext-equiv t (s ∷ []) wk-id-ext₂ : (t s u : Exp) (ϕ : Wk) → t [ id ↦ s ↦ u ] [ ϕ ] ≡ t [ q (q ϕ) ] [ id ↦ (s [ ϕ ]) ↦ (u [ ϕ ]) ] wk-id-ext₂ t s u = wk-id-ext-equiv t (u ∷ s ∷ []) wk-subst-q : (σ : Subst) (ϕ : Wk) → q σ [ q ϕ ] ≗ q (σ [ ϕ ]) wk-subst-q σ ϕ zero = refl wk-subst-q σ ϕ (suc x) = wk-comp-q 0 (σ x) ϕ wk-subst-q₂ : (σ : Subst) (ϕ : Wk) → q (q σ) [ q (q ϕ) ] ≗ q (q (σ [ ϕ ])) wk-subst-q₂ σ ϕ = ≗.trans (wk-subst-q (q σ) (q ϕ)) (subst-q-cong (wk-subst-q σ ϕ)) subst-q-ext-gen : (n : ℕ) (t : Exp) (ts : List Exp) (σ : Subst) → t [ repeat q (n + L.length ts) σ ] [ repeat q n (subst-exts id ts) ] ≡ t [ repeat q n (subst-exts σ ts) ] subst-q-ext-gen n (v x) ts σ = helper n ts x where helper : ∀ n ts x → repeat q (n + L.length ts) σ x [ repeat q n (subst-exts id ts) ] ≡ repeat q n (subst-exts σ ts) x helper zero [] x = subst-app-id (σ x) helper zero (t ∷ ts) zero = refl helper zero (t ∷ ts) (suc x) = trans (exp-wk-ext (repeat q (L.length ts) σ x) (subst-exts id ts) t) (helper zero ts x) helper (suc n) ts zero = refl helper (suc n) ts (suc x) = trans (exp-wk-q′ (repeat q (n + L.length ts) σ x) (repeat q n (subst-exts id ts))) (cong (_[ ⇑ ]) (helper n ts x)) subst-q-ext-gen n ze ts σ = refl subst-q-ext-gen n (su t) ts σ = cong su (subst-q-ext-gen n t ts σ) subst-q-ext-gen n (rec T s r t) ts σ rewrite subst-q-ext-gen n s ts σ | subst-q-ext-gen (2 + n) r ts σ | subst-q-ext-gen n t ts σ = refl subst-q-ext-gen n (Λ t) ts σ = cong Λ (subst-q-ext-gen (1 + n) t ts σ) subst-q-ext-gen n (t $ s) ts σ = cong₂ _$_ (subst-q-ext-gen n t ts σ) (subst-q-ext-gen n s ts σ) subst-q-ext : (t : Exp) (ts : List Exp) (σ : Subst) → t [ repeat q (L.length ts) σ ] [ subst-exts id ts ] ≡ t [ subst-exts σ ts ] subst-q-ext = subst-q-ext-gen 0 subst-q-ext₁ : (t s : Exp) (σ : Subst) → t [ q σ ] [ id ↦ s ] ≡ t [ σ ↦ s ] subst-q-ext₁ t s = subst-q-ext t (s ∷ []) subst-q-ext₂ : (t s s′ : Exp) (σ : Subst) → t [ q (q σ) ] [ id ↦ s ↦ s′ ] ≡ t [ σ ↦ s ↦ s′ ] subst-q-ext₂ t s s′ = subst-q-ext t (s′ ∷ s ∷ []) subst-exts-comb-gen : (σ τ : Subst) (ts : List Exp) → subst-exts σ ts ∙ τ ≗ subst-exts (σ ∙ τ) (L.map (_[ τ ]) ts) subst-exts-comb-gen σ τ [] = ≗.refl subst-exts-comb-gen σ τ (s ∷ ts) = ≗.trans (ext-comp (subst-exts σ ts) τ s) (subst-ext-cong (subst-exts-comb-gen σ τ ts) refl) subst-ext-app-gen : (t : Exp) (σ τ : Subst) (ts : List Exp) → t [ subst-exts σ ts ] [ τ ] ≡ t [ subst-exts (σ ∙ τ) (L.map (_[ τ ]) ts) ] subst-ext-app-gen t σ τ ts = trans (subst-app-comb t (subst-exts σ ts) τ) (subst-transp t (subst-exts-comb-gen σ τ ts)) subst-ext-app₁ : (t s : Exp) (σ τ : Subst) → t [ σ ↦ s ] [ τ ] ≡ t [ (σ ∙ τ) ↦ (s [ τ ]) ] subst-ext-app₁ t s σ τ = subst-ext-app-gen t σ τ (s ∷ []) subst-ext-app₂ : (t s s′ : Exp) (σ τ : Subst) → t [ σ ↦ s ↦ s′ ] [ τ ] ≡ t [ (σ ∙ τ) ↦ (s [ τ ]) ↦ (s′ [ τ ]) ] subst-ext-app₂ t s s′ σ τ = subst-ext-app-gen t σ τ (s′ ∷ s ∷ [])