---
title : "Pure: Pure Type Systems"
permalink : /Pure/
---
Barendregt, H. (1991). Introduction to generalized type
systems. Journal of Functional Programming, 1(2),
125-154. doi:10.1017/S0956796800020025
Fri 8 June
Tried to add weakening directly as a rule. Doing so broke the
definition of renaming, and I could not figure out how to fix it.
Also, need to have variables as a separate construct in order to
define substitution a la Conor. Tried to prove weakening as a derived
rule, but it is tricky. In
Π[_]_⇒_ : ∀ {n} {Γ : Context n} {A : Term n} {B : Term (suc n)} {s t : Sort}
→ Permitted s t
→ Γ ⊢ A ⦂ ⟪ s ⟫
→ Γ , A ⊢ B ⦂ ⟪ t ⟫
-------------------
→ Γ ⊢ Π A ⇒ B ⦂ ⟪ t ⟫
weakening on the middle hypothesis take Γ to Γ , C but weakening on
the last hypothesis takes Γ , A to Γ , C , A, so permutation is required
before one can apply the induction hypothesis. I presume this could
be done similarly to LambdaProp.
## Imports
\begin{code}
module Pure where
\end{code}
\begin{code}
import Relation.Binary.PropositionalEquality as Eq
open Eq using (_≡_; refl; sym; trans; cong)
open import Data.Empty using (⊥; ⊥-elim)
open import Data.Nat using (ℕ; zero; suc; _+_; _∸_)
open import Data.Product using (_×_; Σ; Σ-syntax; proj₁; proj₂)
renaming (_,_ to ⟨_,_⟩)
open import Data.Unit using (⊤; tt)
open import Data.Sum using (_⊎_; inj₁; inj₂)
open import Function using (_∘_)
open import Function.Equivalence using (_⇔_; equivalence)
open import Relation.Nullary using (¬_; Dec; yes; no)
open import Relation.Nullary.Decidable using (map)
open import Relation.Nullary.Negation using (contraposition)
open import Relation.Nullary.Product using (_×-dec_)
\end{code}
## Syntax
Scoped, but not inherently typed.
\begin{code}
infix 6 ƛ_⇒_
infix 7 Π_⇒_
infixr 8 _⇒_
infixl 9 _·_
data Sort : Set where
* : Sort
▢ : Sort
data Var : ℕ → Set where
Z : ∀ {n}
-----------
→ Var (suc n)
S_ : ∀ {n}
→ Var n
-----------
→ Var (suc n)
data Term : ℕ → Set where
⟪_⟫ : ∀ {n}
→ Sort
------
→ Term n
⌊_⌋ : ∀ {n}
→ Var n
------
→ Term n
Π_⇒_ : ∀ {n}
→ Term n
→ Term (suc n)
------------
→ Term n
ƛ_⇒_ : ∀ {n}
→ Term n
→ Term (suc n)
------------
→ Term n
_·_ : ∀ {n}
→ Term n
→ Term n
------
→ Term n
\end{code}
## Renaming
\begin{code}
extr : ∀ {m n} → (Var m → Var n) → (Var (suc m) → Var (suc n))
extr ρ Z = Z
extr ρ (S k) = S (ρ k)
rename : ∀ {m n} → (Var m → Var n) → (Term m → Term n)
rename ρ ⟪ s ⟫ = ⟪ s ⟫
rename ρ ⌊ k ⌋ = ⌊ ρ k ⌋
rename ρ (Π A ⇒ B) = Π rename ρ A ⇒ rename (extr ρ) B
rename ρ (ƛ A ⇒ N) = ƛ rename ρ A ⇒ rename (extr ρ) N
rename ρ (L · M) = rename ρ L · rename ρ M
\end{code}
## Substitution
\begin{code}
exts : ∀ {m n} → (Var m → Term n) → (Var (suc m) → Term (suc n))
exts ρ Z = ⌊ Z ⌋
exts ρ (S k) = rename S_ (ρ k)
subst : ∀ {m n} → (Var m → Term n) → (Term m → Term n)
subst σ ⟪ s ⟫ = ⟪ s ⟫
subst σ ⌊ k ⌋ = σ k
subst σ (Π A ⇒ B) = Π subst σ A ⇒ subst (exts σ) B
subst σ (ƛ A ⇒ N) = ƛ subst σ A ⇒ subst (exts σ) N
subst σ (L · M) = subst σ L · subst σ M
_[_] : ∀ {n} → Term (suc n) → Term n → Term n
_[_] {n} N M = subst {suc n} {n} σ N
where
σ : Var (suc n) → Term n
σ Z = M
σ (S k) = ⌊ k ⌋
\end{code}
## Functions
\begin{code}
_⇒_ : ∀ {n} → Term n → Term n → Term n
A ⇒ B = Π A ⇒ rename S_ B
\end{code}
## Writing variables as numerals
\begin{code}
var : ∀ n → ℕ → Var n
var zero _ = ⊥-elim impossible
where postulate impossible : ⊥
var (suc n) 0 = Z
var (suc n) (suc m) = S (var n m)
infix 10 #_
#_ : ∀ {n} → ℕ → Term n
#_ {n} m = ⌊ var n m ⌋
\end{code}
## Test examples
\begin{code}
Ch : ∀ {n} → Term n
Ch = Π ⟪ * ⟫ ⇒ ((# 0 ⇒ # 0) ⇒ # 0 ⇒ # 0)
-- Ch = Π X ⦂ * ⇒ (X ⇒ X) ⇒ X ⇒ X
two : ∀ {n} → Term n
two = ƛ ⟪ * ⟫ ⇒ ƛ (# 0 ⇒ # 0) ⇒ ƛ # 1 ⇒ # 1 · (# 1 · # 0)
-- two = ƛ X ⦂ * ⇒ ƛ s ⦂ (X ⇒ X) ⇒ ƛ z ⦂ X ⇒ s · (s · z)
four : ∀ {n} → Term n
four = ƛ ⟪ * ⟫ ⇒ ƛ (# 0 ⇒ # 0) ⇒ ƛ # 1 ⇒ # 1 · (# 1 · (# 1 · (# 1 · # 0)))
-- four = ƛ X ⦂ * ⇒ ƛ s ⦂ (X ⇒ X) ⇒ ƛ z ⦂ X ⇒ s · (s · (s · (s · z)))
plus : ∀ {n} → Term n
plus = ƛ Ch ⇒ ƛ Ch ⇒ ƛ ⟪ * ⟫ ⇒ ƛ (# 0 ⇒ # 0) ⇒ ƛ # 1 ⇒
(# 4 · # 2 · # 1 · (# 3 · # 2 · # 1 · # 0))
-- plus = ƛ m ⦂ Ch ⇒ ƛ n ⦂ Ch ⇒ ƛ X ⦂ * ⇒ ƛ s ⦂ (X ⇒ X) ⇒ ƛ z ⦂ X ⇒
-- m X s (n X s z)
\end{code}
## Normal
\begin{code}
data Normal : ∀ {n} → Term n → Set
data Neutral : ∀ {n} → Term n → Set
data Normal where
⟪_⟫ : ∀ {n} {s : Sort}
----------------
→ Normal {n} ⟪ s ⟫
Π_⇒_ : ∀ {n} {A : Term n} {B : Term (suc n)}
→ Normal A
→ Normal B
----------------
→ Normal (Π A ⇒ B)
ƛ_⇒_ : ∀ {n} {A : Term n} {N : Term (suc n)}
→ Normal A
→ Normal N
----------------
→ Normal (ƛ A ⇒ N)
⌈_⌉ : ∀ {n} {M : Term n}
→ Neutral M
---------
→ Normal M
data Neutral where
⌊_⌋ : ∀ {n}
→ (k : Var n)
-------------
→ Neutral ⌊ k ⌋
_·_ : ∀ {n} {L : Term n} {M : Term n}
→ Neutral L
→ Normal M
---------------
→ Neutral (L · M)
\end{code}
Convenient shorthand for neutral variables.
\begin{code}
infix 10 #ᵘ_
#ᵘ_ : ∀ {n} (m : ℕ) → Neutral ⌊ var n m ⌋
#ᵘ_ {n} m = ⌊ var n m ⌋
\end{code}
## Reduction step
\begin{code}
infix 2 _⟶_
Application : ∀ {n} → Term n → Set
Application ⟪ _ ⟫ = ⊥
Application ⌊ _ ⌋ = ⊥
Application (Π _ ⇒ _) = ⊥
Application (ƛ _ ⇒ _) = ⊥
Application (_ · _) = ⊤
data _⟶_ : ∀ {n} → Term n → Term n → Set where
ξ₁ : ∀ {n} {L L′ M : Term n}
→ Application L
→ L ⟶ L′
----------------
→ L · M ⟶ L′ · M
ξ₂ : ∀ {n} {L M M′ : Term n}
→ Neutral L
→ M ⟶ M′
----------------
→ L · M ⟶ L · M′
β : ∀ {n} {A : Term n} {N : Term (suc n)} {M : Term n}
--------------------------------------------------
→ (ƛ A ⇒ N) · M ⟶ N [ M ]
ζΠ₁ : ∀ {n} {A A′ : Term n} {B : Term (suc n)}
→ A ⟶ A′
--------------------
→ Π A ⇒ B ⟶ Π A′ ⇒ B
ζΠ₂ : ∀ {n} {A : Term n} {B B′ : Term (suc n)}
→ B ⟶ B′
--------------------
→ Π A ⇒ B ⟶ Π A ⇒ B′
ζƛ₁ : ∀ {n} {A A′ : Term n} {B : Term (suc n)}
→ A ⟶ A′
--------------------
→ ƛ A ⇒ B ⟶ ƛ A′ ⇒ B
ζƛ₂ : ∀ {n} {A : Term n} {B B′ : Term (suc n)}
→ B ⟶ B′
--------------------
→ ƛ A ⇒ B ⟶ ƛ A ⇒ B′
\end{code}
## Reflexive and transitive closure
\begin{code}
infix 2 _⟶*_
infix 1 begin_
infixr 2 _⟶⟨_⟩_
infix 3 _∎
data _⟶*_ : ∀ {n} → Term n → Term n → Set where
_∎ : ∀ {n} (M : Term n)
---------------------
→ M ⟶* M
_⟶⟨_⟩_ : ∀ {n} (L : Term n) {M N : Term n}
→ L ⟶ M
→ M ⟶* N
---------
→ L ⟶* N
begin_ : ∀ {n} {M N : Term n}
→ M ⟶* N
--------
→ M ⟶* N
\end{code}
## Reflexive, symmetric, and transitive closure
\begin{code}
data _=β_ : ∀ {n} → Term n → Term n → Set where
_∎ : ∀ {n} (M : Term n)
-------------------
→ M =β M
_⟶⟨_⟩_ : ∀ {n} (L : Term n) {M N : Term n}
→ L ⟶ M
→ M =β N
---------
→ L =β N
_⟵⟨_⟩_ : ∀ {n} (L : Term n) {M N : Term n}
→ M ⟶ L
→ M =β N
---------
→ L =β N
begin_ : ∀ {n} {M N : Term n}
→ M =β N
--------
→ M =β N
\end{code}
## Example reduction sequences
\begin{code}
Id : Term zero
Id = Π ⟪ * ⟫ ⇒ (# 0 ⇒ # 0)
-- Id = Π X ⦂ ⟪ * ⟫ ⇒ (X ⇒ X)
id : Term zero
id = ƛ ⟪ * ⟫ ⇒ ƛ # 0 ⇒ # 0
-- id = ƛ X ⦂ ⟪ * ⟫ ⇒ ƛ x ⦂ X ⇒ x
_ : id · Id · id ⟶* id
_ =
begin
id · Id · id
⟶⟨ ξ₁ tt β ⟩
(ƛ Id ⇒ # 0) · id
⟶⟨ β ⟩
id
∎
_ : plus {zero} · two · two ⟶* four
_ =
begin
plus · two · two
⟶⟨ ξ₁ tt β ⟩
(ƛ Ch ⇒ ƛ ⟪ * ⟫ ⇒ ƛ (# 0 ⇒ # 0) ⇒ ƛ # 1 ⇒
two · # 2 · # 1 · (# 3 · # 2 · # 1 · # 0)) · two
⟶⟨ β ⟩
ƛ ⟪ * ⟫ ⇒ ƛ (# 0 ⇒ # 0) ⇒ ƛ # 1 ⇒ two · # 2 · # 1 · (two · # 2 · # 1 · # 0)
⟶⟨ ζƛ₂ (ζƛ₂ (ζƛ₂ (ξ₁ tt (ξ₁ tt β)))) ⟩
ƛ ⟪ * ⟫ ⇒ ƛ (# 0 ⇒ # 0) ⇒ ƛ # 1 ⇒
(ƛ (# 2 ⇒ # 2) ⇒ ƛ # 3 ⇒ # 1 · (# 1 · # 0)) · # 1 · (two · # 2 · # 1 · # 0)
⟶⟨ ζƛ₂ (ζƛ₂ (ζƛ₂ (ξ₁ tt β))) ⟩
ƛ ⟪ * ⟫ ⇒ ƛ (# 0 ⇒ # 0) ⇒ ƛ # 1 ⇒
(ƛ # 2 ⇒ # 2 · (# 2 · # 0)) · (two · # 2 · # 1 · # 0)
⟶⟨ ζƛ₂ (ζƛ₂ (ζƛ₂ β)) ⟩
ƛ ⟪ * ⟫ ⇒ ƛ (# 0 ⇒ # 0) ⇒ ƛ # 1 ⇒ # 1 · (# 1 · (two · # 2 · # 1 · # 0))
⟶⟨ ζƛ₂ (ζƛ₂ (ζƛ₂ (ξ₂ (#ᵘ 1) (ξ₂ (#ᵘ 1) (ξ₁ tt (ξ₁ tt β)))))) ⟩
ƛ ⟪ * ⟫ ⇒ ƛ (# 0 ⇒ # 0) ⇒ ƛ # 1 ⇒ # 1 · (# 1 ·
((ƛ (# 2 ⇒ # 2) ⇒ ƛ # 3 ⇒ # 1 · (# 1 · # 0)) · # 1 · # 0))
⟶⟨ ζƛ₂ (ζƛ₂ (ζƛ₂ (ξ₂ (#ᵘ 1) (ξ₂ (#ᵘ 1) (ξ₁ tt β))))) ⟩
ƛ ⟪ * ⟫ ⇒ ƛ (# 0 ⇒ # 0) ⇒ ƛ # 1 ⇒ # 1 · (# 1 ·
((ƛ # 2 ⇒ # 2 · (# 2 · # 0)) · # 0))
⟶⟨ ζƛ₂ (ζƛ₂ (ζƛ₂ (ξ₂ (#ᵘ 1) (ξ₂ (#ᵘ 1) β)))) ⟩
ƛ ⟪ * ⟫ ⇒ ƛ (# 0 ⇒ # 0) ⇒ ƛ # 1 ⇒ # 1 · (# 1 · (# 1 · (# 1 · # 0)))
∎
\end{code}
## Type rules
\begin{code}
data Permitted : Sort → Sort → Set where
** : Permitted * *
*▢ : Permitted * ▢
▢* : Permitted ▢ *
▢▢ : Permitted ▢ ▢
infix 4 _⊢_⦂_
infix 4 _∋_⦂_
infixl 5 _,_
data Context : ℕ → Set where
∅ : Context zero
_,_ : ∀ {n} → Context n → Term n → Context (suc n)
data _∋_⦂_ : ∀ {n} → Context n → Var n → Term n → Set
data _⊢_⦂_ : ∀ {n} → Context n → Term n → Term n → Set
data _∋_⦂_ where
Z[_] : ∀ {n} {Γ : Context n} {A : Term n} {s : Sort}
→ Γ ⊢ A ⦂ ⟪ s ⟫
-----------------------
→ Γ , A ∋ Z ⦂ rename S_ A
S[_]_ : ∀ {n} {Γ : Context n} {x : Var n} {A B : Term n} {s : Sort}
→ Γ ⊢ A ⦂ ⟪ s ⟫
→ Γ ∋ x ⦂ B
-------------------------
→ Γ , A ∋ S x ⦂ rename S_ B
data _⊢_⦂_ where
⟪*⟫ : ∀ {n} {Γ : Context n}
-----------------
→ Γ ⊢ ⟪ * ⟫ ⦂ ⟪ ▢ ⟫
⌊_⌋ : ∀ {n} {Γ : Context n} {x : Var n} {A : Term n}
→ Γ ∋ x ⦂ A
-------------
→ Γ ⊢ ⌊ x ⌋ ⦂ A
Π[_]_⇒_ : ∀ {n} {Γ : Context n} {A : Term n} {B : Term (suc n)} {s t : Sort}
→ Permitted s t
→ Γ ⊢ A ⦂ ⟪ s ⟫
→ Γ , A ⊢ B ⦂ ⟪ t ⟫
-------------------
→ Γ ⊢ Π A ⇒ B ⦂ ⟪ t ⟫
ƛ[_]_⇒_⦂_ : ∀ {n} {Γ : Context n} {A : Term n} {N B : Term (suc n)} {s t : Sort}
→ Permitted s t
→ Γ ⊢ A ⦂ ⟪ s ⟫
→ Γ , A ⊢ N ⦂ B
→ Γ , A ⊢ B ⦂ ⟪ t ⟫
---------------------
→ Γ ⊢ ƛ A ⇒ N ⦂ Π A ⇒ B
_·_ : ∀ {n} {Γ : Context n} {L M A : Term n} {B : Term (suc n)}
→ Γ ⊢ L ⦂ Π A ⇒ B
→ Γ ⊢ M ⦂ A
-------------------
→ Γ ⊢ L · M ⦂ B [ M ]
Eq : ∀ {n} {Γ : Context n} {M A B : Term n}
→ Γ ⊢ M ⦂ A
→ A =β B
---------
→ Γ ⊢ M ⦂ B
\end{code}
## Rename
\begin{code}
⊢extr : ∀ {m n} {Γ : Context m} {Δ : Context n}
→ (ρ : Var m → Var n)
→ (∀ {w : Var m} {B : Term m} → Γ ∋ w ⦂ B → Δ ∋ ρ w ⦂ rename ρ B)
---------------------------------------------------------------
→ (∀ {w : Var (suc m)} {A : Term m} {B : Term (suc m)}
→ Γ , A ∋ w ⦂ B → Δ , rename ρ A ∋ extr ρ w ⦂ rename (extr ρ) B)
⊢rename : ∀ {m n} {Γ : Context m} {Δ : Context n}
→ (ρ : Var m → Var n)
→ (∀ {w : Var m} {B : Term m} → Γ ∋ w ⦂ B → Δ ∋ ρ w ⦂ rename ρ B)
------------------------------------------------------
→ (∀ {w : Var m} {M A : Term m}
→ Γ ⊢ M ⦂ A → Δ ⊢ rename ρ M ⦂ rename ρ A)
⊢extr ρ ⊢ρ Z[ ⊢A ] = Z[ ⊢rename ρ ⊢ρ ⊢A ]
⊢extr ρ ⊢ρ (S[ ⊢A ] ∋w) = S[ ⊢rename ρ ⊢ρ ⊢A ] (ρ ∋w)
⊢rename = {!!}
{-
⊢rename σ (Ax ∋w) = Ax (σ ∋w)
⊢rename σ (⇒-I ⊢N) = ⇒-I (⊢rename (⊢extr σ) ⊢N)
⊢rename σ (⇒-E ⊢L ⊢M) = ⇒-E (⊢rename σ ⊢L) (⊢rename σ ⊢M)
⊢rename σ ℕ-I₁ = ℕ-I₁
⊢rename σ (ℕ-I₂ ⊢M) = ℕ-I₂ (⊢rename σ ⊢M)
⊢rename σ (ℕ-E ⊢L ⊢M ⊢N) = ℕ-E (⊢rename σ ⊢L) (⊢rename σ ⊢M) (⊢rename (⊢extr σ) ⊢N)
⊢rename σ (Fix ⊢M) = Fix (⊢rename (⊢extr σ) ⊢M)
-}
\end{code}
## Weakening
\begin{code}
{-
weak : ∀ {n} {Γ : Context n} {M : Term n} {A B : Term n} {s : Sort}
→ Γ ⊢ A ⦂ ⟪ s ⟫
→ Γ ⊢ M ⦂ B
---------------------------------
→ Γ , A ⊢ rename S_ M ⦂ rename S_ B
weak ⊢C ⟪*⟫ = ⟪*⟫
weak ⊢C ⌊ ∋x ⌋ = ⌊ S[ ⊢C ] ∋x ⌋
weak ⊢C (Π[ st ] ⊢A ⇒ ⊢B) = {! Π[ st ] weak ⊢A ⇒ weak ⊢B!}
weak ⊢C (ƛ[ x ] ⊢M ⇒ ⊢M₁ ⦂ ⊢M₂) = {!!}
weak ⊢C (⊢M · ⊢M₁) = {!!}
weak ⊢C (Eq ⊢M x) = {!!}
-}
\end{code}
## Substitution in type derivations
\begin{code}
{-
exts : ∀ {m n} → (Var m → Term n) → (Var (suc m) → Term (suc n))
exts ρ Z = ⌊ Z ⌋
exts ρ (S k) = rename S_ (ρ k)
subst : ∀ {m n} → (Var m → Term n) → (Term m → Term n)
subst σ ⟪ s ⟫ = ⟪ s ⟫
subst σ ⌊ k ⌋ = σ k
subst σ (Π A ⇒ B) = Π subst σ A ⇒ subst (exts σ) B
subst σ (ƛ A ⇒ N) = ƛ subst σ A ⇒ subst (exts σ) N
subst σ (L · M) = subst σ L · subst σ M
_[_] : ∀ {n} → Term (suc n) → Term n → Term n
_[_] {n} N M = subst {suc n} {n} σ N
where
σ : Var (suc n) → Term n
σ Z = M
σ (S k) = ⌊ k ⌋
-}
\end{code}
## Test examples are well-typed
\begin{code}
{-
_⊢⇒_ : ∀ {n} {Γ : Context n} {A B : Term n}
→ Γ ⊢ A ⦂ ⟪ * ⟫ → Γ ⊢ B ⦂ ⟪ * ⟫ → Γ ⊢ A ⇒ B ⦂ ⟪ * ⟫
⊢A ⊢⇒ ⊢B = Π[ ** ] ⊢A ⇒ rename S_ ⊢B
-}
-- ⊢Ch : ∅ ⊢ Ch ⦂ ⟪ * ⟫
-- ⊢Ch = Π[ ** ] ⟪ * ⟫ ⇒ Π[ ** ] ⌊ Z ⌋
-- Ch = Π ⟪ * ⟫ ⇒ ((# 0 ⇒ # 0) ⇒ # 0 ⇒ # 0)
-- Ch = Π X ⦂ * ⇒ (X ⇒ X) ⇒ X ⇒ X
{-
two : ∀ {n} → Term n
two = ƛ ⟪ * ⟫ ⇒ ƛ (# 0 ⇒ # 0) ⇒ ƛ # 1 ⇒ # 1 · (# 1 · # 0)
-- two = ƛ X ⦂ * ⇒ ƛ s ⦂ (X ⇒ X) ⇒ ƛ z ⦂ X ⇒ s · (s · z)
four : ∀ {n} → Term n
four = ƛ ⟪ * ⟫ ⇒ ƛ (# 0 ⇒ # 0) ⇒ ƛ # 1 ⇒ # 1 · (# 1 · (# 1 · (# 1 · # 0)))
-- four = ƛ X ⦂ * ⇒ ƛ s ⦂ (X ⇒ X) ⇒ ƛ z ⦂ X ⇒ s · (s · (s · (s · z)))
plus : ∀ {n} → Term n
plus = ƛ Ch ⇒ ƛ Ch ⇒ ƛ ⟪ * ⟫ ⇒ ƛ (# 0 ⇒ # 0) ⇒ ƛ # 1 ⇒
(# 4 · # 2 · # 1 · (# 3 · # 2 · # 1 · # 0))
-- plus = ƛ m ⦂ Ch ⇒ ƛ n ⦂ Ch ⇒ ƛ X ⦂ * ⇒ ƛ s ⦂ (X ⇒ X) ⇒ ƛ z ⦂ X ⇒
-- m X s (n X s z)
-}
\end{code}
## Progress
\begin{code}
{-
data Progress {n} (M : Term n) : Set where
step : ∀ {N : Term n}
→ M ⟶ N
----------
→ Progress M
done :
Normal M
----------
→ Progress M
progress : ∀ {n} → (M : Term n) → Progress M
progress ⌊ x ⌋ = done ⌈ ⌊ x ⌋ ⌉
progress (ƛ N) with progress N
... | step N⟶N′ = step (ζ N⟶N′)
... | done Nⁿ = done (ƛ Nⁿ)
progress (⌊ x ⌋ · M) with progress M
... | step M⟶M′ = step (ξ₂ ⌊ x ⌋ M⟶M′)
... | done Mⁿ = done ⌈ ⌊ x ⌋ · Mⁿ ⌉
progress ((ƛ N) · M) = step β
progress (L@(_ · _) · M) with progress L
... | step L⟶L′ = step (ξ₁ tt L⟶L′)
... | done ⌈ Lᵘ ⌉ with progress M
... | step M⟶M′ = step (ξ₂ Lᵘ M⟶M′)
... | done Mⁿ = done ⌈ Lᵘ · Mⁿ ⌉
-}
\end{code}
## Normalise
\begin{code}
{-
Gas : Set
Gas = ℕ
data Normalise {n} (M : Term n) : Set where
out-of-gas : ∀ {N : Term n}
→ M ⟶* N
-------------
→ Normalise M
normal : ∀ {N : Term n}
→ Gas
→ M ⟶* N
→ Normal N
--------------
→ Normalise M
normalise : ∀ {n}
→ Gas
→ ∀ (M : Term n)
-------------
→ Normalise M
normalise zero L = out-of-gas (L ∎)
normalise (suc g) L with progress L
... | done Lⁿ = normal (suc g) (L ∎) Lⁿ
... | step {M} L⟶M with normalise g M
... | out-of-gas M⟶*N = out-of-gas (L ⟶⟨ L⟶M ⟩ M⟶*N)
... | normal g′ M⟶*N Nⁿ = normal g′ (L ⟶⟨ L⟶M ⟩ M⟶*N) Nⁿ
-}
\end{code}