Renaming

A tool stocked ahead of need: nothing in the trunk consumes it yet, and its first consumers arrive with Part 4's deeper chapters. First, variables.

The syntax chapter pointed out an absence: no substitution, no weakening. The quantifier clauses take bodies in an extended context directly, so the classical apparatus for moving variables around never has to exist. What little variable motion the book does need is covered by one device: renaming, a map ρ : Fin n → Fin m pushed through a formula, with a single correctness theorem that handles weakening, exchange, and contraction in one stroke.

{-# OPTIONS --cubical --safe --guardedness #-}

module FOL.Manipulation.Renaming where

open import Base.Prelude
open import Base.Truth
open import FOL.ZFStructure using ( ZFStructure )
open import FOL.Syntax using
  ( Term; con; var
  ; Formula; _∈̇_; _≐_; _∧̇_; _∨̇_; _⇒̇_; ¬̇_; ⊤̇; ⊥̇; ∃̇_; ∀̇_; ∀̇∈; ∃̇∈ )
import FOL.Semantics

The syntactic layer

Under a binder the renaming must step aside for the freshly bound variable: liftρ ρ keeps variable 0 fixed and shifts everything else through ρ. With that, pushing a renaming through terms and formulas is one clause per constructor; note it moves only variables, leaving constants alone, exactly complementary to the mapFo of the previous chapter.

liftρ :  {n m}  (Fin n  Fin m)  Fin (suc n)  Fin (suc m)
liftρ ρ zero    = zero
liftρ ρ (suc i) = suc (ρ i)

renameTm :  {ℓc} {K : Type ℓc} {n m}  (Fin n  Fin m)  Term K n  Term K m
renameTm ρ (con k) = con k
renameTm ρ (var i) = var (ρ i)

renameFo :  {ℓc} {K : Type ℓc} {n m}  (Fin n  Fin m)  Formula K n  Formula K m
renameFo ρ (t ∈̇ u)  = renameTm ρ t ∈̇ renameTm ρ u
renameFo ρ (t  u)  = renameTm ρ t  renameTm ρ u
renameFo ρ (φ ∧̇ ψ)  = renameFo ρ φ ∧̇ renameFo ρ ψ
renameFo ρ (φ ∨̇ ψ)  = renameFo ρ φ ∨̇ renameFo ρ ψ
renameFo ρ (φ ⇒̇ ψ)  = renameFo ρ φ ⇒̇ renameFo ρ ψ
renameFo ρ (¬̇ φ)    = ¬̇ renameFo ρ φ
renameFo ρ ⊤̇        = ⊤̇
renameFo ρ ⊥̇        = ⊥̇
renameFo ρ (∃̇ φ)    = ∃̇ renameFo (liftρ ρ) φ
renameFo ρ (∀̇ φ)    = ∀̇ renameFo (liftρ ρ) φ
renameFo ρ (∀̇∈ t φ) = ∀̇∈ (renameTm ρ t) (renameFo (liftρ ρ) φ)
renameFo ρ (∃̇∈ t φ) = ∃̇∈ (renameTm ρ t) (renameFo (liftρ ρ) φ)

The semantic layer

When does renaming preserve meaning? Precisely when the two environments say the same things to corresponding variables: Agrees ρ γ δ asks that looking up ρ i in the big environment equals looking up i in the small one, and

agrees∷ shows the condition survives pushing one new value onto both sides, which is what happens under a binder. The development is generic over the truth algebra, the structure, and the constant interpretation.

module Sat { ℓ'} (𝕋 : TruthAlgebra  ℓ') (𝒮 : ZFStructure 𝕋)
           {ℓc} {K : Type ℓc} (ι : K  ZFStructure.S 𝒮) where

  open TruthAlgebra 𝕋
  open ZFStructure 𝒮

  private module Sem = FOL.Semantics 𝕋 𝒮
  open Sem using ( _^_ )
  open Sem.At K ι using ( _⊨_; ⟦_⟧ )

  Agrees :  {n m}  (Fin n  Fin m)  S ^ m  S ^ n  Type 
  Agrees ρ γ δ =  i  lookup (ρ i) γ  lookup i δ

The correctness theorem: a renamed formula in the big environment means the same as the original in the small one. Terms first, then the usual induction, every case a congruence, the binder cases stepping through agrees∷. Weakening (inserting an unused variable), exchange, and contraction are all instances, obtained by choosing ρ.

  agrees∷ :  {n m} {ρ : Fin n  Fin m} {γ : S ^ m} {δ : S ^ n}
            (x : S)  Agrees ρ γ δ  Agrees (liftρ ρ) (x  γ) (x  δ)
  agrees∷ x ag zero    = refl
  agrees∷ x ag (suc i) = ag i

  ⟦⟧-rename :  {n m} (ρ : Fin n  Fin m) (t : Term K n)
              (γ : S ^ m) (δ : S ^ n)  Agrees ρ γ δ
              renameTm ρ t  γ   t  δ
  ⟦⟧-rename ρ (con k) γ δ ag = refl
  ⟦⟧-rename ρ (var i) γ δ ag = ag i

  ⊨-rename :  {n m} (ρ : Fin n  Fin m) (φ : Formula K n)
             (γ : S ^ m) (δ : S ^ n)  Agrees ρ γ δ
            (γ  renameFo ρ φ)  (δ  φ)
  ⊨-rename ρ (t ∈̇ u)  γ δ ag = cong₂ _∈ˢ_ (⟦⟧-rename ρ t γ δ ag) (⟦⟧-rename ρ u γ δ ag)
  ⊨-rename ρ (t  u)  γ δ ag = cong₂ _≈ˢ_ (⟦⟧-rename ρ t γ δ ag) (⟦⟧-rename ρ u γ δ ag)
  ⊨-rename ρ (φ ∧̇ ψ)  γ δ ag = cong₂ _⊓_ (⊨-rename ρ φ γ δ ag) (⊨-rename ρ ψ γ δ ag)
  ⊨-rename ρ (φ ∨̇ ψ)  γ δ ag = cong₂ _⊔_ (⊨-rename ρ φ γ δ ag) (⊨-rename ρ ψ γ δ ag)
  ⊨-rename ρ (φ ⇒̇ ψ)  γ δ ag = cong₂ _⇒_ (⊨-rename ρ φ γ δ ag) (⊨-rename ρ ψ γ δ ag)
  ⊨-rename ρ (¬̇ φ)    γ δ ag = cong ¬_ (⊨-rename ρ φ γ δ ag)
  ⊨-rename ρ ⊤̇        γ δ ag = refl
  ⊨-rename ρ ⊥̇        γ δ ag = refl
  ⊨-rename ρ (∃̇ φ)    γ δ ag = cong ( S) (funExt  x 
    ⊨-rename (liftρ ρ) φ (x  γ) (x  δ) (agrees∷ x ag)))
  ⊨-rename ρ (∀̇ φ)    γ δ ag = cong ( S) (funExt  x 
    ⊨-rename (liftρ ρ) φ (x  γ) (x  δ) (agrees∷ x ag)))
  ⊨-rename ρ (∀̇∈ t φ) γ δ ag = cong ( S) (funExt  x 
    cong₂ _⇒_ (cong (x ∈ˢ_) (⟦⟧-rename ρ t γ δ ag))
              (⊨-rename (liftρ ρ) φ (x  γ) (x  δ) (agrees∷ x ag))))
  ⊨-rename ρ (∃̇∈ t φ) γ δ ag = cong ( S) (funExt  x 
    cong₂ _⊓_ (cong (x ∈ˢ_) (⟦⟧-rename ρ t γ δ ag))
              (⊨-rename (liftρ ρ) φ (x  γ) (x  δ) (agrees∷ x ag))))

Recap

Renaming is the book's entire variable calculus: renameFo on syntax,

⊨-rename on meaning, with Agrees naming the exact condition under which nothing changes. The book's variable machinery now exists, once and in full, ahead of the heavy consumers waiting in Part 4.