csci8980-f21/extra/Pure.lagda
2019-01-08 14:11:20 +00:00

652 lines
17 KiB
Text
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title : "Pure: Pure Type Systems"
layout : page
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}