---
title : "TypedFresh: Fresh variables in substitution"
permalink : /TypedFresh
---
This version uses raw terms. Substitution generates
a fresh name whenever substituting for a lambda term.
## Imports
\begin{code}
module fresh.TypedFresh where
\end{code}
\begin{code}
import Relation.Binary.PropositionalEquality as Eq
open Eq using (_≡_; refl; sym; trans; cong; cong₂; _≢_)
open import Data.Empty using (⊥; ⊥-elim)
open import Data.List using (List; []; _∷_; _++_; map; foldr; filter; concat)
open import Data.Nat using (ℕ; zero; suc; _+_; _∸_; _≤_; _⊔_; _≟_)
open import Data.Nat.Properties using (≤-refl; ≤-trans; m≤m⊔n; n≤m⊔n; 1+n≰n)
open import Data.Product using (_×_; proj₁; proj₂) renaming (_,_ to ⟨_,_⟩)
open import Data.Sum using (_⊎_; inj₁; inj₂)
open import Function using (_∘_)
open import Relation.Nullary using (¬_; Dec; yes; no)
open import Relation.Nullary.Negation using (¬?)
import fresh.Collections
pattern [_] w = w ∷ []
pattern [_,_] w x = w ∷ x ∷ []
pattern [_,_,_] w x y = w ∷ x ∷ y ∷ []
pattern [_,_,_,_] w x y z = w ∷ x ∷ y ∷ z ∷ []
\end{code}
## Syntax
\begin{code}
infixr 5 _⇒_
infixl 5 _,_⦂_
infix 4 _∋_⦂_
infix 4 _⊢_⦂_
infix 5 ƛ_⇒_
infixl 6 `if0_then_else_
infix 7 `suc_ `pred_ `Y_
infixl 8 _·_
Id : Set
Id = ℕ
data Type : Set where
`ℕ : Type
_⇒_ : Type → Type → Type
data Env : Set where
ε : Env
_,_⦂_ : Env → Id → Type → Env
data Term : Set where
⌊_⌋ : Id → Term
ƛ_⇒_ : Id → Term → Term
_·_ : Term → Term → Term
`zero : Term
`suc_ : Term → Term
`pred_ : Term → Term
`if0_then_else_ : Term → Term → Term → Term
`Y_ : Term → Term
data _∋_⦂_ : Env → Id → Type → Set where
Z : ∀ {Γ A x}
-----------------
→ Γ , x ⦂ A ∋ x ⦂ A
S : ∀ {Γ A B x w}
→ w ≢ x
→ Γ ∋ w ⦂ B
-----------------
→ Γ , x ⦂ A ∋ w ⦂ B
data _⊢_⦂_ : Env → Term → Type → Set where
Ax : ∀ {Γ A x}
→ Γ ∋ x ⦂ A
---------------------
→ Γ ⊢ ⌊ x ⌋ ⦂ A
⊢λ : ∀ {Γ x N A B}
→ Γ , x ⦂ A ⊢ N ⦂ B
------------------------
→ Γ ⊢ (ƛ x ⇒ N) ⦂ A ⇒ B
_·_ : ∀ {Γ L M A B}
→ Γ ⊢ L ⦂ A ⇒ B
→ Γ ⊢ M ⦂ A
--------------
→ Γ ⊢ L · M ⦂ B
⊢zero : ∀ {Γ}
--------------
→ Γ ⊢ `zero ⦂ `ℕ
⊢suc : ∀ {Γ M}
→ Γ ⊢ M ⦂ `ℕ
---------------
→ Γ ⊢ `suc M ⦂ `ℕ
⊢pred : ∀ {Γ M}
→ Γ ⊢ M ⦂ `ℕ
----------------
→ Γ ⊢ `pred M ⦂ `ℕ
⊢if0 : ∀ {Γ L M N A}
→ Γ ⊢ L ⦂ `ℕ
→ Γ ⊢ M ⦂ A
→ Γ ⊢ N ⦂ A
----------------------------
→ Γ ⊢ `if0 L then M else N ⦂ A
⊢Y : ∀ {Γ M A}
→ Γ ⊢ M ⦂ A ⇒ A
---------------
→ Γ ⊢ `Y M ⦂ A
\end{code}
## Test examples
\begin{code}
m n s z : Id
p = 0
m = 1
n = 2
s = 3
z = 4
s≢z : s ≢ z
s≢z ()
n≢z : n ≢ z
n≢z ()
n≢s : n ≢ s
n≢s ()
m≢z : m ≢ z
m≢z ()
m≢s : m ≢ s
m≢s ()
m≢n : m ≢ n
m≢n ()
p≢n : p ≢ n
p≢n ()
p≢m : p ≢ m
p≢m ()
two : Term
two = `suc `suc `zero
⊢two : ε ⊢ two ⦂ `ℕ
⊢two = (⊢suc (⊢suc ⊢zero))
plus : Term
plus = `Y (ƛ p ⇒ ƛ m ⇒ ƛ n ⇒ `if0 ⌊ m ⌋ then ⌊ n ⌋ else `suc (⌊ p ⌋ · (`pred ⌊ m ⌋) · ⌊ n ⌋))
⊢plus : ε ⊢ plus ⦂ `ℕ ⇒ `ℕ ⇒ `ℕ
⊢plus = (⊢Y (⊢λ (⊢λ (⊢λ (⊢if0 (Ax ⊢m) (Ax ⊢n) (⊢suc (Ax ⊢p · (⊢pred (Ax ⊢m)) · Ax ⊢n)))))))
where
⊢p = S p≢n (S p≢m Z)
⊢m = S m≢n Z
⊢n = Z
four : Term
four = plus · two · two
⊢four : ε ⊢ four ⦂ `ℕ
⊢four = ⊢plus · ⊢two · ⊢two
Ch : Type
Ch = (`ℕ ⇒ `ℕ) ⇒ `ℕ ⇒ `ℕ
twoCh : Term
twoCh = ƛ s ⇒ ƛ z ⇒ (⌊ s ⌋ · (⌊ s ⌋ · ⌊ z ⌋))
⊢twoCh : ε ⊢ twoCh ⦂ Ch
⊢twoCh = (⊢λ (⊢λ (Ax ⊢s · (Ax ⊢s · Ax ⊢z))))
where
⊢s = S s≢z Z
⊢z = Z
plusCh : Term
plusCh = ƛ m ⇒ ƛ n ⇒ ƛ s ⇒ ƛ z ⇒ ⌊ m ⌋ · ⌊ s ⌋ · (⌊ n ⌋ · ⌊ s ⌋ · ⌊ z ⌋)
⊢plusCh : ε ⊢ plusCh ⦂ Ch ⇒ Ch ⇒ Ch
⊢plusCh = (⊢λ (⊢λ (⊢λ (⊢λ (Ax ⊢m · Ax ⊢s · (Ax ⊢n · Ax ⊢s · Ax ⊢z))))))
where
⊢m = S m≢z (S m≢s (S m≢n Z))
⊢n = S n≢z (S n≢s Z)
⊢s = S s≢z Z
⊢z = Z
fromCh : Term
fromCh = ƛ m ⇒ ⌊ m ⌋ · (ƛ s ⇒ `suc ⌊ s ⌋) · `zero
⊢fromCh : ε ⊢ fromCh ⦂ Ch ⇒ `ℕ
⊢fromCh = (⊢λ (Ax ⊢m · (⊢λ (⊢suc (Ax ⊢s))) · ⊢zero))
where
⊢m = Z
⊢s = Z
fourCh : Term
fourCh = fromCh · (plusCh · twoCh · twoCh)
⊢fourCh : ε ⊢ fourCh ⦂ `ℕ
⊢fourCh = ⊢fromCh · (⊢plusCh · ⊢twoCh · ⊢twoCh)
\end{code}
## Erasure
\begin{code}
lookup : ∀ {Γ x A} → Γ ∋ x ⦂ A → Id
lookup {Γ , x ⦂ A} Z = x
lookup {Γ , x ⦂ A} (S _ ⊢w) = lookup {Γ} ⊢w
erase : ∀ {Γ M A} → Γ ⊢ M ⦂ A → Term
erase (Ax ⊢w) = ⌊ lookup ⊢w ⌋
erase (⊢λ {x = x} ⊢N) = ƛ x ⇒ erase ⊢N
erase (⊢L · ⊢M) = erase ⊢L · erase ⊢M
erase (⊢zero) = `zero
erase (⊢suc ⊢M) = `suc (erase ⊢M)
erase (⊢pred ⊢M) = `pred (erase ⊢M)
erase (⊢if0 ⊢L ⊢M ⊢N) = `if0 (erase ⊢L) then (erase ⊢M) else (erase ⊢N)
erase (⊢Y ⊢M) = `Y (erase ⊢M)
\end{code}
### Properties of erasure
\begin{code}
cong₃ : ∀ {A B C D : Set} (f : A → B → C → D) {s t u v x y} →
s ≡ t → u ≡ v → x ≡ y → f s u x ≡ f t v y
cong₃ f refl refl refl = refl
lookup-lemma : ∀ {Γ x A} → (⊢x : Γ ∋ x ⦂ A) → lookup ⊢x ≡ x
lookup-lemma Z = refl
lookup-lemma (S _ ⊢w) = lookup-lemma ⊢w
erase-lemma : ∀ {Γ M A} → (⊢M : Γ ⊢ M ⦂ A) → erase ⊢M ≡ M
erase-lemma (Ax ⊢x) = cong ⌊_⌋ (lookup-lemma ⊢x)
erase-lemma (⊢λ {x = x} ⊢N) = cong (ƛ x ⇒_) (erase-lemma ⊢N)
erase-lemma (⊢L · ⊢M) = cong₂ _·_ (erase-lemma ⊢L) (erase-lemma ⊢M)
erase-lemma (⊢zero) = refl
erase-lemma (⊢suc ⊢M) = cong `suc_ (erase-lemma ⊢M)
erase-lemma (⊢pred ⊢M) = cong `pred_ (erase-lemma ⊢M)
erase-lemma (⊢if0 ⊢L ⊢M ⊢N) = cong₃ `if0_then_else_
(erase-lemma ⊢L) (erase-lemma ⊢M) (erase-lemma ⊢N)
erase-lemma (⊢Y ⊢M) = cong `Y_ (erase-lemma ⊢M)
\end{code}
## Substitution
### Lists as sets
\begin{code}
open fresh.Collections (Id) (_≟_)
\end{code}
### Free variables
\begin{code}
free : Term → List Id
free (⌊ x ⌋) = [ x ]
free (ƛ x ⇒ N) = free N \\ x
free (L · M) = free L ++ free M
free (`zero) = []
free (`suc M) = free M
free (`pred M) = free M
free (`if0 L then M else N) = free L ++ free M ++ free N
free (`Y M) = free M
\end{code}
### Fresh identifier
\begin{code}
fresh : List Id → Id
fresh = foldr _⊔_ 0 ∘ map suc
⊔-lemma : ∀ {w xs} → w ∈ xs → suc w ≤ fresh xs
⊔-lemma {_} {_ ∷ xs} here = m≤m⊔n _ (fresh xs)
⊔-lemma {w} {x ∷ xs} (there x∈) = ≤-trans (⊔-lemma {w} {xs} x∈) (n≤m⊔n (suc x) (fresh xs))
fresh-lemma : ∀ {x xs} → x ∈ xs → x ≢ fresh xs
fresh-lemma x∈ refl = 1+n≰n (⊔-lemma x∈)
\end{code}
### Identifier maps
\begin{code}
∅ : Id → Term
∅ x = ⌊ x ⌋
infixl 5 _,_↦_
_,_↦_ : (Id → Term) → Id → Term → (Id → Term)
(ρ , x ↦ M) w with w ≟ x
... | yes _ = M
... | no _ = ρ w
\end{code}
### Substitution
\begin{code}
subst : List Id → (Id → Term) → Term → Term
subst ys ρ (⌊ x ⌋) = ρ x
subst ys ρ (ƛ x ⇒ N) = ƛ y ⇒ subst (y ∷ ys) (ρ , x ↦ ⌊ y ⌋) N
where
y = fresh ys
subst ys ρ (L · M) = subst ys ρ L · subst ys ρ M
subst ys ρ (`zero) = `zero
subst ys ρ (`suc M) = `suc (subst ys ρ M)
subst ys ρ (`pred M) = `pred (subst ys ρ M)
subst ys ρ (`if0 L then M else N)
= `if0 (subst ys ρ L) then (subst ys ρ M) else (subst ys ρ N)
subst ys ρ (`Y M) = `Y (subst ys ρ M)
_[_:=_] : Term → Id → Term → Term
N [ x := M ] = subst (free M ++ (free N \\ x)) (∅ , x ↦ M) N
\end{code}
### Testing substitution
\begin{code}
_ : (⌊ s ⌋ · ⌊ s ⌋ · ⌊ z ⌋) [ z := `zero ] ≡ (⌊ s ⌋ · ⌊ s ⌋ · `zero)
_ = refl
_ : (⌊ s ⌋ · ⌊ s ⌋ · ⌊ z ⌋)[ s := (ƛ m ⇒ `suc ⌊ m ⌋) ] [ z := `zero ]
≡ ((ƛ p ⇒ `suc ⌊ p ⌋) · (ƛ p ⇒ `suc ⌊ p ⌋) · `zero)
_ = refl
_ : (ƛ m ⇒ ⌊ m ⌋ · ⌊ n ⌋) [ n := ⌊ m ⌋ ] ≡ (ƛ n ⇒ ⌊ n ⌋ · ⌊ m ⌋)
_ = refl
_ : subst [ m , n ] (∅ , m ↦ ⌊ n ⌋ , n ↦ ⌊ m ⌋) (⌊ m ⌋ · ⌊ n ⌋) ≡ (⌊ n ⌋ · ⌊ m ⌋)
_ = refl
\end{code}
## Values
\begin{code}
data Value : Term → Set where
Zero :
----------
Value `zero
Suc : ∀ {V}
→ Value V
--------------
→ Value (`suc V)
Fun : ∀ {x N}
---------------
→ Value (ƛ x ⇒ N)
\end{code}
## Reduction
\begin{code}
infix 4 _⟶_
data _⟶_ : Term → Term → Set where
ξ-·₁ : ∀ {L L′ M}
→ L ⟶ L′
----------------
→ L · M ⟶ L′ · M
ξ-·₂ : ∀ {V M M′}
→ Value V
→ M ⟶ M′
----------------
→ V · M ⟶ V · M′
β-⇒ : ∀ {x N V}
→ Value V
------------------------------
→ (ƛ x ⇒ N) · V ⟶ N [ x := V ]
ξ-suc : ∀ {M M′}
→ M ⟶ M′
------------------
→ `suc M ⟶ `suc M′
ξ-pred : ∀ {M M′}
→ M ⟶ M′
--------------------
→ `pred M ⟶ `pred M′
β-pred-zero :
---------------------
`pred `zero ⟶ `zero
β-pred-suc : ∀ {V}
→ Value V
--------------------
→ `pred (`suc V) ⟶ V
ξ-if0 : ∀ {L L′ M N}
→ L ⟶ L′
----------------------------------------------
→ `if0 L then M else N ⟶ `if0 L′ then M else N
β-if0-zero : ∀ {M N}
------------------------------
→ `if0 `zero then M else N ⟶ M
β-if0-suc : ∀ {V M N}
→ Value V
---------------------------------
→ `if0 (`suc V) then M else N ⟶ N
ξ-Y : ∀ {M M′}
→ M ⟶ M′
--------------
→ `Y M ⟶ `Y M′
β-Y : ∀ {V x N}
→ Value V
→ V ≡ ƛ x ⇒ N
------------------------
→ `Y V ⟶ N [ x := `Y V ]
\end{code}
## Reflexive and transitive closure
\begin{code}
infix 2 _⟶*_
infix 1 begin_
infixr 2 _⟶⟨_⟩_
infix 3 _∎
data _⟶*_ : Term → Term → Set where
_∎ : ∀ (M : Term)
-------------
→ M ⟶* M
_⟶⟨_⟩_ : ∀ (L : Term) {M N}
→ L ⟶ M
→ M ⟶* N
---------
→ L ⟶* N
begin_ : ∀ {M N} → (M ⟶* N) → (M ⟶* N)
begin M⟶*N = M⟶*N
\end{code}
## Canonical forms
\begin{code}
data Canonical : Term → Type → Set where
Zero :
------------------
Canonical `zero `ℕ
Suc : ∀ {V}
→ Canonical V `ℕ
---------------------
→ Canonical (`suc V) `ℕ
Fun : ∀ {x N A B}
→ ε , x ⦂ A ⊢ N ⦂ B
------------------------------
→ Canonical (ƛ x ⇒ N) (A ⇒ B)
\end{code}
## Canonical forms lemma
Every typed value is canonical.
\begin{code}
canonical : ∀ {V A}
→ ε ⊢ V ⦂ A
→ Value V
-------------
→ Canonical V A
canonical ⊢zero Zero = Zero
canonical (⊢suc ⊢V) (Suc VV) = Suc (canonical ⊢V VV)
canonical (⊢λ ⊢N) Fun = Fun ⊢N
\end{code}
Every canonical form has a type and a value.
\begin{code}
type : ∀ {V A}
→ Canonical V A
-------------
→ ε ⊢ V ⦂ A
type Zero = ⊢zero
type (Suc CV) = ⊢suc (type CV)
type (Fun ⊢N) = ⊢λ ⊢N
value : ∀ {V A}
→ Canonical V A
-------------
→ Value V
value Zero = Zero
value (Suc CV) = Suc (value CV)
value (Fun ⊢N) = Fun
\end{code}
## Progress
\begin{code}
data Progress (M : Term) (A : Type) : Set where
step : ∀ {N}
→ M ⟶ N
----------
→ Progress M A
done :
Canonical M A
-------------
→ Progress M A
progress : ∀ {M A} → ε ⊢ M ⦂ A → Progress M A
progress (Ax ())
progress (⊢λ ⊢N) = done (Fun ⊢N)
progress (⊢L · ⊢M) with progress ⊢L
... | step L⟶L′ = step (ξ-·₁ L⟶L′)
... | done (Fun _) with progress ⊢M
... | step M⟶M′ = step (ξ-·₂ Fun M⟶M′)
... | done CM = step (β-⇒ (value CM))
progress ⊢zero = done Zero
progress (⊢suc ⊢M) with progress ⊢M
... | step M⟶M′ = step (ξ-suc M⟶M′)
... | done CM = done (Suc CM)
progress (⊢pred ⊢M) with progress ⊢M
... | step M⟶M′ = step (ξ-pred M⟶M′)
... | done Zero = step β-pred-zero
... | done (Suc CM) = step (β-pred-suc (value CM))
progress (⊢if0 ⊢L ⊢M ⊢N) with progress ⊢L
... | step L⟶L′ = step (ξ-if0 L⟶L′)
... | done Zero = step β-if0-zero
... | done (Suc CM) = step (β-if0-suc (value CM))
progress (⊢Y ⊢M) with progress ⊢M
... | step M⟶M′ = step (ξ-Y M⟶M′)
... | done (Fun _) = step (β-Y Fun refl)
\end{code}
## Preservation
### Lemmas about free variables
\begin{code}
id : ∀ {X : Set} → X → X
id x = x
fr-⌊⌋ : ∀ {x} → x ∈ free ⌊ x ⌋
fr-⌊⌋ = here
fr-ƛ : ∀ {x N xs} → free (ƛ x ⇒ N) ⊆ xs → free N ⊆ x ∷ xs
fr-ƛ = \\-to-∷
{-
fr-ƛ : ∀ {x N} → free (ƛ x ⇒ N) ⊆ free N
fr-ƛ = proj₁ ∘ \\-to-∈-≢
fr-ƛ-≢ : ∀ {w x N} → w ∈ free (ƛ x ⇒ N) → w ≢ x
fr-ƛ-≢ {w} {x} {N} = proj₂ ∘ \\-to-∈-≢ {w} {x} {free N}
-}
fr-·₁ : ∀ {L M xs Γ A B} → Γ ⊢ L ⦂ A ⇒ B → Γ ⊢ M ⦂ A → free (L · M) ⊆ xs → free L ⊆ xs
fr-·₁ ⊢L ⊢M ⊆xs = ⊆xs ∘ ⊆-++₁
fr-·₂ : ∀ {L M xs Γ A B} → Γ ⊢ L ⦂ A ⇒ B → Γ ⊢ M ⦂ A → free (L · M) ⊆ xs → free M ⊆ xs
fr-·₂ ⊢L ⊢M ⊆xs = ⊆xs ∘ ⊆-++₂
fr-suc : ∀ {M} → free M ⊆ free (`suc M)
fr-suc = id
fr-pred : ∀ {M} → free M ⊆ free (`pred M)
fr-pred = id
fr-if0₁ : ∀ {L M N xs Γ A} → Γ ⊢ L ⦂ `ℕ → Γ ⊢ M ⦂ A → Γ ⊢ N ⦂ A
→ free (`if0 L then M else N) ⊆ xs → free L ⊆ xs
fr-if0₁ ⊢L ⊢M ⊢N ⊆xs = ⊆xs ∘ ⊆-++₁
fr-if0₂ : ∀ {L M N xs Γ A} → Γ ⊢ L ⦂ `ℕ → Γ ⊢ M ⦂ A → Γ ⊢ N ⦂ A
→ free (`if0 L then M else N) ⊆ xs → free M ⊆ xs
fr-if0₂ {L} ⊢L ⊢M ⊢N ⊆xs = ⊆xs ∘ ⊆-++₂ {free L} ∘ ⊆-++₁
fr-if0₃ : ∀ {L M N xs Γ A} → Γ ⊢ L ⦂ `ℕ → Γ ⊢ M ⦂ A → Γ ⊢ N ⦂ A
→ free (`if0 L then M else N) ⊆ xs → free N ⊆ xs
fr-if0₃ {L} ⊢L ⊢M ⊢N ⊆xs = ⊆xs ∘ ⊆-++₂ {free L} ∘ ⊆-++₂
fr-Y : ∀ {M} → free M ⊆ free (`Y M)
fr-Y = id
\end{code}
### Domain of an environment
\begin{code}
dom : Env → List Id
dom ε = []
dom (Γ , x ⦂ A) = x ∷ dom Γ
dom-lemma : ∀ {Γ y B} → Γ ∋ y ⦂ B → y ∈ dom Γ
dom-lemma Z = here
dom-lemma (S x≢y ⊢y) = there (dom-lemma ⊢y)
free-lemma : ∀ {Γ M A} → Γ ⊢ M ⦂ A → free M ⊆ dom Γ
free-lemma (Ax ⊢x) w∈ with w∈
... | here = dom-lemma ⊢x
... | there ()
free-lemma {Γ} (⊢λ {N = N} ⊢N) = ∷-to-\\ (free-lemma ⊢N)
free-lemma (⊢L · ⊢M) w∈ with ++-to-⊎ w∈
... | inj₁ ∈L = free-lemma ⊢L ∈L
... | inj₂ ∈M = free-lemma ⊢M ∈M
free-lemma ⊢zero ()
free-lemma (⊢suc ⊢M) w∈ = free-lemma ⊢M w∈
free-lemma (⊢pred ⊢M) w∈ = free-lemma ⊢M w∈
free-lemma (⊢if0 ⊢L ⊢M ⊢N) w∈
with ++-to-⊎ w∈
... | inj₁ ∈L = free-lemma ⊢L ∈L
... | inj₂ ∈MN with ++-to-⊎ ∈MN
... | inj₁ ∈M = free-lemma ⊢M ∈M
... | inj₂ ∈N = free-lemma ⊢N ∈N
free-lemma (⊢Y ⊢M) w∈ = free-lemma ⊢M w∈
\end{code}
### Renaming
\begin{code}
⊢rename : ∀ {Γ Δ xs}
→ (∀ {x A} → x ∈ xs → Γ ∋ x ⦂ A → Δ ∋ x ⦂ A)
--------------------------------------------------
→ (∀ {M A} → free M ⊆ xs → Γ ⊢ M ⦂ A → Δ ⊢ M ⦂ A)
⊢rename ⊢σ ⊆xs (Ax ⊢x) = Ax (⊢σ ∈xs ⊢x)
where
∈xs = ⊆xs fr-⌊⌋
⊢rename {Γ} {Δ} {xs} ⊢σ ⊆xs (⊢λ {x = x} {N = N} {A = A} ⊢N)
= ⊢λ (⊢rename {Γ′} {Δ′} {xs′} ⊢σ′ ⊆xs′ ⊢N)
where
Γ′ = Γ , x ⦂ A
Δ′ = Δ , x ⦂ A
xs′ = x ∷ xs
⊢σ′ : ∀ {w B} → w ∈ xs′ → Γ′ ∋ w ⦂ B → Δ′ ∋ w ⦂ B
⊢σ′ w∈′ Z = Z
⊢σ′ w∈′ (S w≢ ⊢w) = S w≢ (⊢σ ∈w ⊢w)
where
∈w = there⁻¹ w∈′ w≢
⊆xs′ : free N ⊆ xs′
⊆xs′ = fr-ƛ {x} {N} ⊆xs
⊢rename ⊢σ ⊆xs (⊢L · ⊢M) = ⊢rename ⊢σ L⊆ ⊢L · ⊢rename ⊢σ M⊆ ⊢M
where
L⊆ = fr-·₁ ⊢L ⊢M ⊆xs
M⊆ = fr-·₂ ⊢L ⊢M ⊆xs
⊢rename ⊢σ ⊆xs (⊢zero) = ⊢zero
⊢rename ⊢σ ⊆xs (⊢suc ⊢M) = ⊢suc (⊢rename ⊢σ ⊆xs ⊢M)
⊢rename ⊢σ ⊆xs (⊢pred ⊢M) = ⊢pred (⊢rename ⊢σ ⊆xs ⊢M)
⊢rename ⊢σ ⊆xs (⊢if0 ⊢L ⊢M ⊢N)
= ⊢if0 (⊢rename ⊢σ L⊆ ⊢L) (⊢rename ⊢σ M⊆ ⊢M) (⊢rename ⊢σ N⊆ ⊢N)
where
L⊆ = fr-if0₁ ⊢L ⊢M ⊢N ⊆xs
M⊆ = fr-if0₂ ⊢L ⊢M ⊢N ⊆xs
N⊆ = fr-if0₃ ⊢L ⊢M ⊢N ⊆xs
⊢rename ⊢σ ⊆xs (⊢Y ⊢M) = ⊢Y (⊢rename ⊢σ ⊆xs ⊢M)
\end{code}
### Substitution preserves types
\begin{code}
⊢subst : ∀ {Γ Δ xs ys ρ}
→ (∀ {x} → x ∈ xs → free (ρ x) ⊆ ys)
→ (∀ {x A} → x ∈ xs → Γ ∋ x ⦂ A → Δ ⊢ ρ x ⦂ A)
-------------------------------------------------------------
→ (∀ {M A} → free M ⊆ xs → Γ ⊢ M ⦂ A → Δ ⊢ subst ys ρ M ⦂ A)
⊢subst Σ ⊢ρ ⊆xs (Ax ⊢x)
= ⊢ρ (⊆xs here) ⊢x
⊢subst {Γ} {Δ} {xs} {ys} {ρ} Σ ⊢ρ ⊆xs (⊢λ {x = x} {N = N} {A = A} ⊢N)
= ⊢λ {x = y} {A = A} (⊢subst {Γ′} {Δ′} {xs′} {ys′} {ρ′} Σ′ ⊢ρ′ ⊆xs′ ⊢N)
where
y = fresh ys
Γ′ = Γ , x ⦂ A
Δ′ = Δ , y ⦂ A
xs′ = x ∷ xs
ys′ = y ∷ ys
ρ′ = ρ , x ↦ ⌊ y ⌋
Σ′ : ∀ {w} → w ∈ xs′ → free (ρ′ w) ⊆ ys′
Σ′ {w} w∈′ with w ≟ x
... | yes refl = ⊆-++₁
... | no w≢ = (there {x = y}) ∘ Σ (there⁻¹ w∈′ w≢)
-- (⊆-++₂ {[ y ]} {ys}) ∘ Σ (there⁻¹ w∈′ w≢)
⊆xs′ : free N ⊆ xs′
⊆xs′ = \\-to-∷ ⊆xs
⊢σ : ∀ {w C} → w ∈ ys → Δ ∋ w ⦂ C → Δ′ ∋ w ⦂ C
⊢σ w∈ ⊢w = S (fresh-lemma w∈) ⊢w
⊢ρ′ : ∀ {w C} → w ∈ xs′ → Γ′ ∋ w ⦂ C → Δ′ ⊢ ρ′ w ⦂ C
⊢ρ′ {w} _ Z with w ≟ x
... | yes _ = Ax Z
... | no w≢ = ⊥-elim (w≢ refl)
⊢ρ′ {w} w∈′ (S w≢ ⊢w) with w ≟ x
... | yes refl = ⊥-elim (w≢ refl)
... | no _ = ⊢rename {Δ} {Δ′} {ys} ⊢σ (Σ w∈) (⊢ρ w∈ ⊢w)
where
w∈ = there⁻¹ w∈′ w≢
⊢subst Σ ⊢ρ ⊆xs (_·_ {L = L} {M = M} ⊢L ⊢M)
= ⊢subst Σ ⊢ρ L⊆ ⊢L · ⊢subst Σ ⊢ρ M⊆ ⊢M
where
L⊆ = trans-⊆ ⊆-++₁ ⊆xs
M⊆ = trans-⊆ (⊆-++₂ {free L} {free M}) ⊆xs
⊢subst Σ ⊢ρ ⊆xs ⊢zero = ⊢zero
⊢subst Σ ⊢ρ ⊆xs (⊢suc ⊢M) = ⊢suc (⊢subst Σ ⊢ρ ⊆xs ⊢M)
⊢subst Σ ⊢ρ ⊆xs (⊢pred ⊢M) = ⊢pred (⊢subst Σ ⊢ρ ⊆xs ⊢M)
⊢subst Σ ⊢ρ ⊆xs (⊢if0 {L = L} {M = M} {N = N} ⊢L ⊢M ⊢N)
= ⊢if0 (⊢subst Σ ⊢ρ L⊆ ⊢L) (⊢subst Σ ⊢ρ M⊆ ⊢M) (⊢subst Σ ⊢ρ N⊆ ⊢N)
where
L⊆ = trans-⊆ ⊆-++₁ ⊆xs
M⊆ = trans-⊆ ⊆-++₁ (trans-⊆ (⊆-++₂ {free L}) ⊆xs)
N⊆ = trans-⊆ (⊆-++₂ {free M} {free N}) (trans-⊆ (⊆-++₂ {free L}) ⊆xs)
⊢subst Σ ⊢ρ ⊆xs (⊢Y ⊢M) = ⊢Y (⊢subst Σ ⊢ρ ⊆xs ⊢M)
⊢substitution : ∀ {Γ x A N B M} →
Γ , x ⦂ A ⊢ N ⦂ B →
Γ ⊢ M ⦂ A →
--------------------
Γ ⊢ N [ x := M ] ⦂ B
⊢substitution {Γ} {x} {A} {N} {B} {M} ⊢N ⊢M =
⊢subst {Γ′} {Γ} {xs} {ys} {ρ} Σ ⊢ρ {N} {B} ⊆xs ⊢N
where
Γ′ = Γ , x ⦂ A
xs = free N
ys = free M ++ (free N \\ x)
ρ = ∅ , x ↦ M
Σ : ∀ {w} → w ∈ xs → free (ρ w) ⊆ ys
Σ {w} w∈ y∈ with w ≟ x
... | yes _ = ⊆-++₁ y∈
... | no w≢ rewrite ∈-[_] y∈ = ⊆-++₂ {free M} {(free N) \\ x} (∈-≢-to-\\ w∈ w≢)
⊢ρ : ∀ {w B} → w ∈ xs → Γ′ ∋ w ⦂ B → Γ ⊢ ρ w ⦂ B
⊢ρ {w} w∈ Z with w ≟ x
... | yes _ = ⊢M
... | no w≢ = ⊥-elim (w≢ refl)
⊢ρ {w} w∈ (S w≢ ⊢w) with w ≟ x
... | yes refl = ⊥-elim (w≢ refl)
... | no _ = Ax ⊢w
⊆xs : free N ⊆ xs
⊆xs x∈ = x∈
\end{code}
### Preservation
\begin{code}
preservation : ∀ {Γ M N A}
→ Γ ⊢ M ⦂ A
→ M ⟶ N
---------
→ Γ ⊢ N ⦂ A
preservation (Ax ⊢x) ()
preservation (⊢λ ⊢N) ()
preservation (⊢L · ⊢M) (ξ-·₁ L⟶) = preservation ⊢L L⟶ · ⊢M
preservation (⊢V · ⊢M) (ξ-·₂ _ M⟶) = ⊢V · preservation ⊢M M⟶
preservation ((⊢λ ⊢N) · ⊢W) (β-⇒ _) = ⊢substitution ⊢N ⊢W
preservation (⊢zero) ()
preservation (⊢suc ⊢M) (ξ-suc M⟶) = ⊢suc (preservation ⊢M M⟶)
preservation (⊢pred ⊢M) (ξ-pred M⟶) = ⊢pred (preservation ⊢M M⟶)
preservation (⊢pred ⊢zero) (β-pred-zero) = ⊢zero
preservation (⊢pred (⊢suc ⊢M)) (β-pred-suc _) = ⊢M
preservation (⊢if0 ⊢L ⊢M ⊢N) (ξ-if0 L⟶) = ⊢if0 (preservation ⊢L L⟶) ⊢M ⊢N
preservation (⊢if0 ⊢zero ⊢M ⊢N) β-if0-zero = ⊢M
preservation (⊢if0 (⊢suc ⊢V) ⊢M ⊢N) (β-if0-suc _) = ⊢N
preservation (⊢Y ⊢M) (ξ-Y M⟶) = ⊢Y (preservation ⊢M M⟶)
preservation (⊢Y (⊢λ ⊢N)) (β-Y _ refl) = ⊢substitution ⊢N (⊢Y (⊢λ ⊢N))
\end{code}
## Normalise
\begin{code}
data Normalise {M A} (⊢M : ε ⊢ M ⦂ A) : Set where
out-of-gas : ∀ {N} → M ⟶* N → ε ⊢ N ⦂ A → Normalise ⊢M
normal : ∀ {V} → ℕ → Canonical V A → M ⟶* V → Normalise ⊢M
normalise : ∀ {L A} → ℕ → (⊢L : ε ⊢ L ⦂ A) → Normalise ⊢L
normalise {L} zero ⊢L = out-of-gas (L ∎) ⊢L
normalise {L} (suc m) ⊢L with progress ⊢L
... | done CL = normal (suc m) CL (L ∎)
... | step L⟶M with preservation ⊢L L⟶M
... | ⊢M with normalise m ⊢M
... | out-of-gas M⟶*N ⊢N = out-of-gas (L ⟶⟨ L⟶M ⟩ M⟶*N) ⊢N
... | normal n CV M⟶*V = normal n CV (L ⟶⟨ L⟶M ⟩ M⟶*V)
\end{code}
## Test case
\begin{code}
_ : plus · two · two ⟶* (`suc (`suc (`suc (`suc `zero))))
_ =
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`suc (`suc `zero))
· (`suc (`suc `zero))
⟶⟨ ξ-·₁ (ξ-·₁ (β-Y Fun refl)) ⟩
(ƛ 0 ⇒
(ƛ 1 ⇒
`if0 ⌊ 0 ⌋ then ⌊ 1 ⌋ else
`suc
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`pred ⌊ 0 ⌋)
· ⌊ 1 ⌋))
· (`suc (`suc `zero))
· (`suc (`suc `zero))
⟶⟨ ξ-·₁ (β-⇒ (Suc (Suc Zero))) ⟩
(ƛ 0 ⇒
`if0 `suc (`suc `zero) then ⌊ 0 ⌋ else
`suc
(`Y
(ƛ 1 ⇒
(ƛ 2 ⇒
(ƛ 3 ⇒
`if0 ⌊ 2 ⌋ then ⌊ 3 ⌋ else `suc ⌊ 1 ⌋ · (`pred ⌊ 2 ⌋) · ⌊ 3 ⌋))))
· (`pred (`suc (`suc `zero)))
· ⌊ 0 ⌋)
· (`suc (`suc `zero))
⟶⟨ β-⇒ (Suc (Suc Zero)) ⟩
`if0 `suc (`suc `zero) then `suc (`suc `zero) else
`suc
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`pred (`suc (`suc `zero)))
· (`suc (`suc `zero))
⟶⟨ β-if0-suc (Suc Zero) ⟩
`suc
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`pred (`suc (`suc `zero)))
· (`suc (`suc `zero))
⟶⟨ ξ-suc (ξ-·₁ (ξ-·₁ (β-Y Fun refl))) ⟩
`suc
(ƛ 0 ⇒
(ƛ 1 ⇒
`if0 ⌊ 0 ⌋ then ⌊ 1 ⌋ else
`suc
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`pred ⌊ 0 ⌋)
· ⌊ 1 ⌋))
· (`pred (`suc (`suc `zero)))
· (`suc (`suc `zero))
⟶⟨ ξ-suc (ξ-·₁ (ξ-·₂ Fun (β-pred-suc (Suc Zero)))) ⟩
`suc
(ƛ 0 ⇒
(ƛ 1 ⇒
`if0 ⌊ 0 ⌋ then ⌊ 1 ⌋ else
`suc
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`pred ⌊ 0 ⌋)
· ⌊ 1 ⌋))
· (`suc `zero)
· (`suc (`suc `zero))
⟶⟨ ξ-suc (ξ-·₁ (β-⇒ (Suc Zero))) ⟩
`suc
(ƛ 0 ⇒
`if0 `suc `zero then ⌊ 0 ⌋ else
`suc
(`Y
(ƛ 1 ⇒
(ƛ 2 ⇒
(ƛ 3 ⇒
`if0 ⌊ 2 ⌋ then ⌊ 3 ⌋ else `suc ⌊ 1 ⌋ · (`pred ⌊ 2 ⌋) · ⌊ 3 ⌋))))
· (`pred (`suc `zero))
· ⌊ 0 ⌋)
· (`suc (`suc `zero))
⟶⟨ ξ-suc (β-⇒ (Suc (Suc Zero))) ⟩
`suc
(`if0 `suc `zero then `suc (`suc `zero) else
`suc
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`pred (`suc `zero))
· (`suc (`suc `zero)))
⟶⟨ ξ-suc (β-if0-suc Zero) ⟩
`suc
(`suc
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`pred (`suc `zero))
· (`suc (`suc `zero)))
⟶⟨ ξ-suc (ξ-suc (ξ-·₁ (ξ-·₁ (β-Y Fun refl)))) ⟩
`suc
(`suc
(ƛ 0 ⇒
(ƛ 1 ⇒
`if0 ⌊ 0 ⌋ then ⌊ 1 ⌋ else
`suc
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`pred ⌊ 0 ⌋)
· ⌊ 1 ⌋))
· (`pred (`suc `zero))
· (`suc (`suc `zero)))
⟶⟨ ξ-suc (ξ-suc (ξ-·₁ (ξ-·₂ Fun (β-pred-suc Zero)))) ⟩
`suc
(`suc
(ƛ 0 ⇒
(ƛ 1 ⇒
`if0 ⌊ 0 ⌋ then ⌊ 1 ⌋ else
`suc
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`pred ⌊ 0 ⌋)
· ⌊ 1 ⌋))
· `zero
· (`suc (`suc `zero)))
⟶⟨ ξ-suc (ξ-suc (ξ-·₁ (β-⇒ Zero))) ⟩
`suc
(`suc
(ƛ 0 ⇒
`if0 `zero then ⌊ 0 ⌋ else
`suc
(`Y
(ƛ 1 ⇒
(ƛ 2 ⇒
(ƛ 3 ⇒
`if0 ⌊ 2 ⌋ then ⌊ 3 ⌋ else `suc ⌊ 1 ⌋ · (`pred ⌊ 2 ⌋) · ⌊ 3 ⌋))))
· (`pred `zero)
· ⌊ 0 ⌋)
· (`suc (`suc `zero)))
⟶⟨ ξ-suc (ξ-suc (β-⇒ (Suc (Suc Zero)))) ⟩
`suc
(`suc
(`if0 `zero then `suc (`suc `zero) else
`suc
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`pred `zero)
· (`suc (`suc `zero))))
⟶⟨ ξ-suc (ξ-suc β-if0-zero) ⟩
`suc (`suc (`suc (`suc `zero)))
∎
\end{code}
### An issue
While executing normalise works fine, checking that the
result is as computed takes forever. Hence, it is commented
out below.
\begin{code}
{-
_ : normalise 100 ⊢four ≡
normal 86 (Suc (Suc (Suc (Suc Zero))))
((`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`suc (`suc `zero))
· (`suc (`suc `zero))
⟶⟨ ξ-·₁ (ξ-·₁ (β-Y Fun refl)) ⟩
(ƛ 0 ⇒
(ƛ 1 ⇒
`if0 ⌊ 0 ⌋ then ⌊ 1 ⌋ else
`suc
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`pred ⌊ 0 ⌋)
· ⌊ 1 ⌋))
· (`suc (`suc `zero))
· (`suc (`suc `zero))
⟶⟨ ξ-·₁ (β-⇒ (Suc (Suc Zero))) ⟩
(ƛ 0 ⇒
`if0 `suc (`suc `zero) then ⌊ 0 ⌋ else
`suc
(`Y
(ƛ 1 ⇒
(ƛ 2 ⇒
(ƛ 3 ⇒
`if0 ⌊ 2 ⌋ then ⌊ 3 ⌋ else `suc ⌊ 1 ⌋ · (`pred ⌊ 2 ⌋) · ⌊ 3 ⌋))))
· (`pred (`suc (`suc `zero)))
· ⌊ 0 ⌋)
· (`suc (`suc `zero))
⟶⟨ β-⇒ (Suc (Suc Zero)) ⟩
`if0 `suc (`suc `zero) then `suc (`suc `zero) else
`suc
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`pred (`suc (`suc `zero)))
· (`suc (`suc `zero))
⟶⟨ β-if0-suc (Suc Zero) ⟩
`suc
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`pred (`suc (`suc `zero)))
· (`suc (`suc `zero))
⟶⟨ ξ-suc (ξ-·₁ (ξ-·₁ (β-Y Fun refl))) ⟩
`suc
(ƛ 0 ⇒
(ƛ 1 ⇒
`if0 ⌊ 0 ⌋ then ⌊ 1 ⌋ else
`suc
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`pred ⌊ 0 ⌋)
· ⌊ 1 ⌋))
· (`pred (`suc (`suc `zero)))
· (`suc (`suc `zero))
⟶⟨ ξ-suc (ξ-·₁ (ξ-·₂ Fun (β-pred-suc (Suc Zero)))) ⟩
`suc
(ƛ 0 ⇒
(ƛ 1 ⇒
`if0 ⌊ 0 ⌋ then ⌊ 1 ⌋ else
`suc
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`pred ⌊ 0 ⌋)
· ⌊ 1 ⌋))
· (`suc `zero)
· (`suc (`suc `zero))
⟶⟨ ξ-suc (ξ-·₁ (β-⇒ (Suc Zero))) ⟩
`suc
(ƛ 0 ⇒
`if0 `suc `zero then ⌊ 0 ⌋ else
`suc
(`Y
(ƛ 1 ⇒
(ƛ 2 ⇒
(ƛ 3 ⇒
`if0 ⌊ 2 ⌋ then ⌊ 3 ⌋ else `suc ⌊ 1 ⌋ · (`pred ⌊ 2 ⌋) · ⌊ 3 ⌋))))
· (`pred (`suc `zero))
· ⌊ 0 ⌋)
· (`suc (`suc `zero))
⟶⟨ ξ-suc (β-⇒ (Suc (Suc Zero))) ⟩
`suc
(`if0 `suc `zero then `suc (`suc `zero) else
`suc
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`pred (`suc `zero))
· (`suc (`suc `zero)))
⟶⟨ ξ-suc (β-if0-suc Zero) ⟩
`suc
(`suc
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`pred (`suc `zero))
· (`suc (`suc `zero)))
⟶⟨ ξ-suc (ξ-suc (ξ-·₁ (ξ-·₁ (β-Y Fun refl)))) ⟩
`suc
(`suc
(ƛ 0 ⇒
(ƛ 1 ⇒
`if0 ⌊ 0 ⌋ then ⌊ 1 ⌋ else
`suc
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`pred ⌊ 0 ⌋)
· ⌊ 1 ⌋))
· (`pred (`suc `zero))
· (`suc (`suc `zero)))
⟶⟨ ξ-suc (ξ-suc (ξ-·₁ (ξ-·₂ Fun (β-pred-suc Zero)))) ⟩
`suc
(`suc
(ƛ 0 ⇒
(ƛ 1 ⇒
`if0 ⌊ 0 ⌋ then ⌊ 1 ⌋ else
`suc
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`pred ⌊ 0 ⌋)
· ⌊ 1 ⌋))
· `zero
· (`suc (`suc `zero)))
⟶⟨ ξ-suc (ξ-suc (ξ-·₁ (β-⇒ Zero))) ⟩
`suc
(`suc
(ƛ 0 ⇒
`if0 `zero then ⌊ 0 ⌋ else
`suc
(`Y
(ƛ 1 ⇒
(ƛ 2 ⇒
(ƛ 3 ⇒
`if0 ⌊ 2 ⌋ then ⌊ 3 ⌋ else `suc ⌊ 1 ⌋ · (`pred ⌊ 2 ⌋) · ⌊ 3 ⌋))))
· (`pred `zero)
· ⌊ 0 ⌋)
· (`suc (`suc `zero)))
⟶⟨ ξ-suc (ξ-suc (β-⇒ (Suc (Suc Zero)))) ⟩
`suc
(`suc
(`if0 `zero then `suc (`suc `zero) else
`suc
(`Y
(ƛ 0 ⇒
(ƛ 1 ⇒
(ƛ 2 ⇒
`if0 ⌊ 1 ⌋ then ⌊ 2 ⌋ else `suc ⌊ 0 ⌋ · (`pred ⌊ 1 ⌋) · ⌊ 2 ⌋))))
· (`pred `zero)
· (`suc (`suc `zero))))
⟶⟨ ξ-suc (ξ-suc β-if0-zero) ⟩ `suc (`suc (`suc (`suc `zero))) ∎)
_ = refl
-}
\end{code}
### Ulf writes
I believe the problem you've run into is that we don't have explicit sharing in the
internal terms. The normal form of `normalise 100 ⊢four` is small, but the weak-head
normal form is huge, and the type checker compares terms for equality by successive
weak-head reduction steps. The lack of explicit sharing means that evaluation won't be
shared across reduction steps.
Here are some numbers:
n size of whnf of `normalise n ⊢four` (#nodes in syntax tree)
1 916
2 122,597
3 53,848,821
4 ??
100 ????
### Discussion
(Notes to myself)
I can remove the `ys` argument from `subst` by always
computing it as `frees ρ M`. As I step into an abstraction,
this will automatically add the renaming of the bound
variable, since the bound variable gets added to `M` and
its renaming gets added to `ρ`.
A possible new version.
Simpler to state, is it simpler to prove?
What may be tricky to establish is that sufficient
renaming occurs to justify the `≢` term added to `S`.
It may be hard to establish because we use it
when we instantiate `⊢rename′ {Δ} {Δ , y ⦂ A} (S w≢y)`
and the problem is that `w≢y` for every `w` in
`free (ρ x)`, but there may be other `w` in `Δ`.
Bugger. But I think the theorems are true despite
this problem in the proof, so there may be a way
around it.
frees : (Id → Term) → Term → List Id
frees ρ M = concat (map (free ∘ ρ) (free M))
subst′ : (Id → Term) → Term → Term
subst′ ρ M = subst (frees ρ M) ρ M
⊢rename′ : ∀ {Γ Δ M A}
→ (∀ {w B} → Γ ∋ w ⦂ B → Δ ∋ w ⦂ B)
→ Γ ⊢ M ⦂ A
----------------------------------
→ Δ ⊢ M ⦂ A
⊢rename′ = {!!}
⊢subst′ : ∀ {Γ Δ ρ M A}
→ (∀ {w B} → Γ ∋ w ⦂ B → Δ ⊢ ρ w ⦂ B)
→ Γ ⊢ M ⦂ A
------------------------------------
→ Δ ⊢ subst′ ρ M ⦂ A
⊢subst′ = {!!}
I expect `⊢rename′` is easy to show.
I think `⊢subst′` is hard to show,
The difficult part is to establish the argument to `⊢rename′`,
since I can only create a variable that is fresh with regard to
names in frees, not all names in the domain of `Δ`.
Nonetheless, `⊢subst` is obviously true, since it is a corollary
of the current version of `⊢subst`.
Stepping into a subterm, just need to precompose `ρ` with a
lemma stating that the free variables of the subterm are
a subset of the free variables of the term.