module Declarative.RenamingSubstitution where
open import Data.Fin using (Fin) open import Function using (_∘_) open import Relation.Binary.PropositionalEquality using (_≡_;refl;sym;trans;subst;cong) open import Data.Vec using (Vec;[];_∷_;lookup) open import Utils using (Kind;*;K) open import Utils.List using (List;IList;[];_∷_) open import Type using (Ctx⋆;_⊢⋆_;Φ;Ψ;A;B) open _⊢⋆_ import Type.RenamingSubstitution as ⋆ open import Type.Equality using (ren≡β;sub≡β;≡2β;_≡β_) open _≡β_ open import Declarative as Dec using (Ctx;Γ;Δ;_∋_;conv∋;_⊢_;conv⊢;piBody;btype-ren;btype-sub;muPat;muArg;typeOf;typeOf∋) open Ctx open _∋_ open _⊢_
A term renaming maps every term variables in a context Γ
to a
variable in context Δ
. It is indexed by a type renaming which does
the same thing for type variables.
Ren : ∀ Γ Δ → ⋆.Ren Φ Ψ → Set Ren Γ Δ ρ = ∀{A} → Γ ∋ A → Δ ∋ ⋆.ren ρ A
Extending a renaming to work on longer context extended by an
additional variable - used when going under a binder. It maps the new
variable Z
to Z
and shift everything else along.
ext : (ρ⋆ : ⋆.Ren Φ Ψ) → Ren Γ Δ ρ⋆ → ∀{B} ------------------------------- → Ren (Γ , B) (Δ , ⋆.ren ρ⋆ B) ρ⋆ ext _ ρ Z = Z ext _ ρ (S x) = S (ρ x)
Extending a renaming to work on a context extended by one additional type variable - used when going under a type binder. This doesn’t actually change any term variables, it is a case of managing the type information.
ext⋆ : (ρ⋆ : ⋆.Ren Φ Ψ) → Ren Γ Δ ρ⋆ → ∀ {K} -------------------------------- → Ren (Γ ,⋆ K) (Δ ,⋆ K) (⋆.ext ρ⋆) ext⋆ _ ρ (T x) = conv∋ refl (trans (sym (⋆.ren-comp _)) (⋆.ren-comp _)) (T (ρ x))
ren : (ρ⋆ : ⋆.Ren Φ Ψ) → Ren Γ Δ ρ⋆ ------------------------------- → (∀{A} → Γ ⊢ A → Δ ⊢ ⋆.ren ρ⋆ A) ren-ConstrArgs : ∀ {Φ} {Ψ} {Γ : Ctx Φ} {Δ : Ctx Ψ} (ρ⋆ : ⋆.Ren Φ Ψ) (ρ : Ren Γ Δ ρ⋆) {Ts : List (Φ ⊢⋆ *)} (cs : Dec.ConstrArgs Γ Ts) → Dec.ConstrArgs Δ (⋆.ren-List ρ⋆ Ts) ren-ConstrArgs ρ⋆ ρ [] = [] ren-ConstrArgs ρ⋆ ρ (c ∷ cs) = (ren ρ⋆ ρ c) ∷ (ren-ConstrArgs ρ⋆ ρ cs) lem-ren-mkCaseType : ∀ {Φ} {Ψ} {Γ : Ctx Φ} {Δ : Ctx Ψ} (ρ⋆ : ⋆.Ren Φ Ψ) (ρ : Ren Γ Δ ρ⋆) {A : Φ ⊢⋆ *} (As : List (Φ ⊢⋆ *)) → ⋆.ren ρ⋆ (Dec.mkCaseType A As) ≡ Dec.mkCaseType (⋆.ren ρ⋆ A) (⋆.ren-List ρ⋆ As) lem-ren-mkCaseType ρ⋆ ρ [] = refl lem-ren-mkCaseType ρ⋆ ρ (A ∷ As) = cong (⋆.ren _ _ ⇒_) (lem-ren-mkCaseType ρ⋆ ρ As) ren-Cases : ∀ {Φ} {Ψ} {Γ : Ctx Φ} {Δ : Ctx Ψ} (ρ⋆ : ⋆.Ren Φ Ψ) (ρ : Ren Γ Δ ρ⋆) {A : Φ ⊢⋆ *} {n} {Tss : Vec (List (Φ ⊢⋆ *)) n} (cases : Dec.Cases Γ A Tss) → Dec.Cases Δ (⋆.ren ρ⋆ A) (⋆.ren-VecList ρ⋆ Tss) ren-Cases ρ⋆ ρ Dec.[] = Dec.[] ren-Cases ρ⋆ ρ (Dec._∷_ {Ts = As} c cs) = subst (_ ⊢_) (lem-ren-mkCaseType ρ⋆ ρ As) (ren ρ⋆ ρ c) Dec.∷ (ren-Cases ρ⋆ ρ cs) ren _ ρ (` x) = ` (ρ x) ren _ ρ (ƛ L) = ƛ (ren _ (ext _ ρ) L) ren _ ρ (L · M) = ren _ ρ L · ren _ ρ M ren _ ρ (Λ L) = Λ (ren _ (ext⋆ _ ρ) L) ren ρ⋆ ρ (L ·⋆ A) = conv⊢ refl (⋆.ren-Π A (piBody L) ρ⋆) (ren _ ρ L ·⋆ ⋆.ren ρ⋆ A) ren _ ρ (wrap A B L) = wrap _ _ (conv⊢ refl (⋆.ren-μ _ A B) (ren _ ρ L)) ren _ ρ (unwrap L) = conv⊢ refl (sym (⋆.ren-μ _ _ _)) (unwrap (ren _ ρ L)) ren _ ρ (conv p L) = conv (ren≡β _ p) (ren _ ρ L) ren ρ⋆ ρ (con {A} cn p) = con {A = A} cn (trans≡β (ren≡β ρ⋆ p) (≡2β (sym (⋆.sub∅-ren A ρ⋆)))) ren ρ⋆ _ (builtin b) = conv⊢ refl (btype-ren b ρ⋆) (builtin b) ren _ _ (error A) = error (⋆.ren _ A) ren ρ⋆ ρ (constr e Tss refl cs) = constr e (⋆.ren-VecList ρ⋆ Tss) (sym (⋆.lookup-ren-VecList ρ⋆ e Tss)) (ren-ConstrArgs ρ⋆ ρ cs) ren ρ⋆ ρ (case L cases) = case (ren ρ⋆ ρ L) (ren-Cases ρ⋆ ρ cases)
Weakening a term by an additional type variable
weaken : Γ ⊢ A --------- → Γ , B ⊢ A weaken x = conv⊢ refl (⋆.ren-id _) (ren _ (conv∋ refl (sym (⋆.ren-id _)) ∘ S) x)
weaken⋆ : Γ ⊢ A ------------------- → Γ ,⋆ K ⊢ ⋆.weaken A weaken⋆ x = ren _ T x
A substitution maps term variables to terms. It is indexed by a type substitution.
Sub : ∀ Γ Δ → ⋆.Sub Φ Ψ → Set Sub Γ Δ σ = ∀{A} → Γ ∋ A → Δ ⊢ ⋆.sub σ A
Extend a substitution by an additional term variable. Used for going under binders.
exts : (σ⋆ : ⋆.Sub Φ Ψ) → Sub Γ Δ σ⋆ → ∀ {B} ------------------------------- → Sub (Γ , B) (Δ , ⋆.sub σ⋆ B) σ⋆ exts σ⋆ σ Z = ` Z exts σ⋆ σ (S x) = weaken (σ x)
Extend a substitution by an additional type variable. Used for going under type binders.
exts⋆ : (σ⋆ : ⋆.Sub Φ Ψ) → Sub Γ Δ σ⋆ → ∀{K} --------------------------------- → Sub (Γ ,⋆ K) (Δ ,⋆ K) (⋆.exts σ⋆) exts⋆ _ σ (T {A = A} x) = conv⊢ refl (trans (sym (⋆.ren-sub A)) (⋆.sub-ren A)) (weaken⋆ (σ x))
sub : (σ⋆ : ⋆.Sub Φ Ψ) → Sub Γ Δ σ⋆ ----------------------------- → ∀{A} → Γ ⊢ A → Δ ⊢ ⋆.sub σ⋆ A sub-ConstrArgs : ∀ {Φ} {Ψ} {Γ : Ctx Φ} {Δ : Ctx Ψ} (σ⋆ : ⋆.Sub Φ Ψ) (σ : Sub Γ Δ σ⋆) {Ts : List (Φ ⊢⋆ *)} (cs : Dec.ConstrArgs Γ Ts) → Dec.ConstrArgs Δ (⋆.sub-List σ⋆ Ts) sub-ConstrArgs σ⋆ σ [] = [] sub-ConstrArgs σ⋆ σ (c ∷ cs) = (sub σ⋆ σ c) ∷ (sub-ConstrArgs σ⋆ σ cs) lem-sub-mkCaseType : ∀ {Φ} {Ψ} {Γ : Ctx Φ} {Δ : Ctx Ψ} (σ⋆ : ⋆.Sub Φ Ψ) (σ : Sub Γ Δ σ⋆) {A : Φ ⊢⋆ *} (As : List (Φ ⊢⋆ *)) → ⋆.sub σ⋆ (Dec.mkCaseType A As) ≡ Dec.mkCaseType (⋆.sub σ⋆ A) (⋆.sub-List σ⋆ As) lem-sub-mkCaseType σ⋆ σ [] = refl lem-sub-mkCaseType σ⋆ σ (A ∷ As) = cong (⋆.sub σ⋆ A ⇒_) (lem-sub-mkCaseType σ⋆ σ As) sub-Cases : ∀ {Φ} {Ψ} {Γ : Ctx Φ} {Δ : Ctx Ψ} (σ⋆ : ⋆.Sub Φ Ψ) (σ : Sub Γ Δ σ⋆) {A : Φ ⊢⋆ *} {n} {Tss : Vec (List (Φ ⊢⋆ *)) n} (cases : Dec.Cases Γ A Tss) → Dec.Cases Δ (⋆.sub σ⋆ A) (⋆.sub-VecList σ⋆ Tss) sub-Cases σ⋆ σ Dec.[] = Dec.[] sub-Cases σ⋆ σ (Dec._∷_ {Ts = As} c cases) = subst (_ ⊢_) (lem-sub-mkCaseType σ⋆ σ As) (sub σ⋆ σ c) Dec.∷ (sub-Cases σ⋆ σ cases) sub _ σ (` k) = σ k sub _ σ (ƛ L) = ƛ (sub _ (exts _ σ) L) sub _ σ (L · M) = sub _ σ L · sub _ σ M sub _ σ (Λ L) = Λ (sub _ (exts⋆ _ σ) L) sub σ⋆ σ (L ·⋆ A) = conv⊢ refl (⋆.sub-Π A (piBody L) σ⋆) (sub σ⋆ σ L ·⋆ ⋆.sub σ⋆ A) sub _ σ (wrap A B L) = wrap _ _ (conv⊢ refl (⋆.sub-μ _ A B) (sub _ σ L)) sub _ σ (unwrap L) = conv⊢ refl (sym (⋆.sub-μ _ (muPat L) (muArg L))) (unwrap (sub _ σ L)) sub _ σ (conv p L) = conv (sub≡β _ p) (sub _ σ L) sub σ⋆ _ (con {A} cn p) = con {A = A} cn (trans≡β (sub≡β σ⋆ p) (≡2β (sym (⋆.sub∅-sub A σ⋆)))) sub _ _ (builtin b) = conv⊢ refl (btype-sub b _) (builtin b) sub _ _ (error A) = error (⋆.sub _ A) sub σ⋆ σ (constr e Tss refl cs) = constr e (⋆.sub-VecList σ⋆ Tss) (sym (⋆.lookup-sub-VecList σ⋆ e Tss)) (sub-ConstrArgs σ⋆ σ cs) sub σ⋆ σ (case L cases) = case (sub σ⋆ σ L) (sub-Cases σ⋆ σ cases)
Extending a substitution by a term. Substitutions are implemented as
functions but they could also be implemented as lists. This operation
corresponds to cons (_∷_
) for backwards lists.
subcons : (σ⋆ : ⋆.Sub Φ Ψ) → (Sub Γ Δ σ⋆) → ∀{A} → Δ ⊢ ⋆.sub σ⋆ A ---------------- → Sub (Γ , A) Δ σ⋆ subcons _ σ L Z = L subcons _ σ L (S x) = σ x
Substitute a single variable in a term. Used to specify the beta-rule for appliction in reduction.
_[_] : Γ , A ⊢ B → Γ ⊢ A --------- → Γ ⊢ B L [ M ] = conv⊢ refl (⋆.sub-id (typeOf L)) (sub _ (subcons ` (` ∘ conv∋ refl (sym (⋆.sub-id _))) (conv⊢ refl (sym (⋆.sub-id (typeOf M))) M)) L)
Substitute a single type variable in a term. Used to specify the beta-rule for type instantiation in reduction.
_[_]⋆ : Γ ,⋆ K ⊢ B → (A : Φ ⊢⋆ K) ------------- → Γ ⊢ B ⋆.[ A ] L [ A ]⋆ = sub _ (λ {(T x) → conv⊢ refl (trans (sym (⋆.sub-id _)) (⋆.sub-ren (typeOf∋ x))) (` x)}) L