------------------------------------------------------------------------ -- Substitutions ------------------------------------------------------------------------ module SimplyTyped.Substitution where open import SimplyTyped.TypeSystem open import SimplyTyped.ContextExtension import SimplyTyped.Environment as Env open import Function hiding (_∋_) ------------------------------------------------------------------------ -- General substitution machinery -- Uses idea from "Type-Preserving Renaming and Substitution" by Conor -- McBride to enable defining both term and variable substitutions -- without having to write several functions which traverse terms. -- Definition of what a substitution is. module SubstDef (_•_ : TmLike) -- The substitution replaces variables -- with this kind of "term". where -- Substitutions of type Γ ⇒ Δ, when applied, take things with -- variables in Γ and give things with variables in Δ. (This concept -- is sometimes written with the arrow in the other direction.) -- Substitutions are defined in terms of environments. infix 10 _⇒_ private module Dummy {Δ : Ctxt} where open Env (_•_ Δ) public open Dummy public using (∅; _▷_; lookup) _⇒_ : Ctxt → Ctxt → Set Γ ⇒ Δ = Dummy.Env {Δ} Γ -- The type of functions applying substitutions to things. Applier : TmLike → TmLike → Set Applier _•₁_ _•₂_ = ∀ {Γ Δ τ} → Γ •₁ τ → Γ ⇒ Δ → Δ •₂ τ -- You get lots of substitution machinery defined for you (see -- below) if you define a SubstKit, ... record SubstKit : Set where field vr : ∀ {Γ τ} → Γ ∋ τ → Γ • τ weaken : ∀ {Γ σ τ} → Γ • τ → (Γ ▻ σ) • τ tm : ∀ {Γ τ} → Γ • τ → Γ ⊢ τ -- ...and more if you define a SubstKit⁺. record SubstKit⁺ : Set where field kit : SubstKit _/•_ : Applier _•_ _•_ open SubstDef using (SubstKit; SubstKit⁺) hiding (module SubstKit) -- Various substitution-related functions. module Subst {_•_ : TmLike} (kit : SubstKit _•_) where open SubstDef _•_ public open SubstKit kit infix 70 _↑ infix 48 _[_] -- Weakening of substitutions. wk⇒ : ∀ {Γ Δ σ} → Γ ⇒ Δ → Γ ⇒ Δ ▻ σ wk⇒ ∅ = ∅ wk⇒ (ρ ▷ t) = wk⇒ ρ ▷ weaken t -- Lifting of substitutions. _↑ : ∀ {Γ Δ σ} → Γ ⇒ Δ → Γ ▻ σ ⇒ Δ ▻ σ ρ ↑ = wk⇒ ρ ▷ vr vz -- Identity. idˢ : ∀ {Γ} → Γ ⇒ Γ idˢ {Γ = ε} = ∅ idˢ {Γ = Γ ▻ τ} = idˢ ↑ -- Weakening. wk : ∀ {Γ σ} → Γ ⇒ Γ ▻ σ wk = wk⇒ idˢ -- Substitution of a single variable. sub : ∀ {Γ τ} → Γ • τ → Γ ▻ τ ⇒ Γ sub t = idˢ ▷ t -- Substitution application for terms. _[_] : Applier _⊢_ _⊢_ var x [ ρ ] = tm (lookup x ρ) ƛ t [ ρ ] = ƛ (t [ ρ ↑ ]) t₁ · t₂ [ ρ ] = (t₁ [ ρ ]) · (t₂ [ ρ ]) -- Multiple weakenings. wk⇒⋆ : ∀ {Γ Δ} Δ⁺ → Γ ⇒ Δ → Γ ⇒ Δ ▻▻ Δ⁺ wk⇒⋆ ε ρ = ρ wk⇒⋆ (Δ⁺ ▻ σ) ρ = wk⇒ (wk⇒⋆ Δ⁺ ρ) wk⋆ : ∀ {Γ} Γ⁺ → Γ ⇒ Γ ▻▻ Γ⁺ wk⋆ Γ⁺ = wk⇒⋆ Γ⁺ idˢ -- Subst⁺ defines composition. This function uses a stronger -- substitution kit, which is sometimes defined using the Subst module -- (see the examples below); this is the reason for placing -- composition in a separate module. module Subst⁺ {_•_ : TmLike} (kit⁺ : SubstKit⁺ _•_) where open SubstDef.SubstKit⁺ kit⁺ open Subst kit public infixl 70 _∘ˢ_ _∘ˢ_ : ∀ {Γ Δ X} → Γ ⇒ Δ → Δ ⇒ X → Γ ⇒ X ∅ ∘ˢ ρ₂ = ∅ (ρ₁ ▷ t) ∘ˢ ρ₂ = ρ₁ ∘ˢ ρ₂ ▷ (t /• ρ₂) ------------------------------------------------------------------------ -- Instantiations of the general structures above -- Variables. varKit : SubstKit _∋_ varKit = record { vr = id ; weaken = vs ; tm = var } varKit⁺ : SubstKit⁺ _∋_ varKit⁺ = record { kit = varKit ; _/•_ = Subst.lookup varKit } module VarSubst where open Subst⁺ varKit⁺ public -- Terms. tmKit : SubstKit _⊢_ tmKit = record { vr = var ; weaken = λ t → t [ wk ] ; tm = id } where open VarSubst tmKit⁺ : SubstKit⁺ _⊢_ tmKit⁺ = record { kit = tmKit ; _/•_ = Subst._[_] tmKit } module TmSubst where open Subst⁺ tmKit⁺ public