revised notation for Lambda, PandP

This commit is contained in:
wadler 2018-06-29 12:11:41 -03:00
parent 62b25bad76
commit ba4dd3e84b
2 changed files with 408 additions and 405 deletions

View file

@ -11,7 +11,7 @@ module plta.Lambda where
[This chapter was originally based on Chapter _Stlc_
of _Software Foundations_ (_Programming Language Foundations_).
It has now been updated, but if you spot any plagiarism
please let me know. -- P]
please let me know. P]
The _lambda-calculus_, first published by the logician Alonzo Church in
1932, is a core calculus with only three syntactic constructs:
@ -67,7 +67,7 @@ open import Relation.Nullary.Negation using (¬?)
Terms have seven constructs. Three are for the core lambda calculus:
* Variables `⌊ x ⌋`
* Variables `` x`
* Abstractions `ƛ x ⇒ N`
* Applications `L · M`
@ -94,7 +94,7 @@ correspond to introduction rules and deconstructors to eliminators.
Here is the syntax of terms in BNF.
L, M, N ::=
⌊ x ⌋ | ƛ x ⇒ N | L · M |
` x | ƛ x ⇒ N | L · M |
`zero | `suc M | `case L [zero⇒ M |suc x ⇒ N] |
μ x ⇒ M
@ -107,9 +107,10 @@ infix 6 ƛ_⇒_
infix 6 μ_⇒_
infixl 7 _·_
infix 8 `suc_
infix 9 `_
data Term : Set where
⌊_⌋ : Id → Term
`_ : Id → Term
ƛ_⇒_ : Id → Term → Term
_·_ : Term → Term → Term
`zero : Term
@ -134,9 +135,9 @@ two = `suc `suc `zero
plus : Term
plus = μ "+" ⇒ ƛ "m" ⇒ ƛ "n" ⇒
`case ⌊ "m" ⌋
[zero⇒ ⌊ "n" ⌋
|suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋) ]
`case ` "m"
[zero⇒ ` "n"
|suc "m" ⇒ `suc (` "+" · ` "m" · ` "n") ]
four : Term
four = plus · two · two
@ -160,14 +161,14 @@ function that adds Church numerals, a function to compute successor,
and a term that computes two plus two.
\begin{code}
twoᶜ : Term
twoᶜ = ƛ "s" ⇒ ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋)
twoᶜ = ƛ "s" ⇒ ƛ "z" ⇒ ` "s" · (` "s" · ` "z")
plusᶜ : Term
plusᶜ = ƛ "m" ⇒ ƛ "n" ⇒ ƛ "s" ⇒ ƛ "z" ⇒
⌊ "m" ⌋ · ⌊ "s" ⌋ · (⌊ "n" ⌋ · ⌊ "s" ⌋ · ⌊ "z" ⌋)
` "m" · ` "s" · (` "n" · ` "s" · ` "z")
sucᶜ : Term
sucᶜ = ƛ "n" ⇒ `suc (⌊ "n" ⌋)
sucᶜ = ƛ "n" ⇒ `suc (` "n")
fourᶜ : Term
fourᶜ = plusᶜ · twoᶜ · twoᶜ · sucᶜ · `zero
@ -198,7 +199,7 @@ two natural numbers.
### Formal vs informal
In informal presentation of formal semantics, one uses choice of
variable name to disambiguate and writes `x` rather than `⌊ x ⌋`
variable name to disambiguate and writes `x` rather than `` x`
for a term that is a variable. Agda requires we distinguish.
Similarly, informal presentation often use the same notation for
@ -218,10 +219,10 @@ and `N` the _body_ of the abstraction. A central feature
of lambda calculus is that consistent renaming of bound variables
leaves the meaning of a term unchanged. Thus the five terms
* `` ƛ "s" ⇒ ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋) ``
* `` ƛ "f" ⇒ ƛ "x" ⇒ ⌊ "f" ⌋ · (⌊ "f" ⌋ · ⌊ "x" ⌋) ``
* `` ƛ "sam" ⇒ ƛ "zelda" ⇒ ⌊ "sam" ⌋ · (⌊ "sam" ⌋ · ⌊ "zelda" ⌋) ``
* `` ƛ "z" ⇒ ƛ "s" ⇒ ⌊ "z" ⌋ · (⌊ "z" ⌋ · ⌊ "s" ⌋) ``
* `` ƛ "s" ⇒ ƛ "z" ⇒ ` "s" · (` "s" · ` "z") ``
* `` ƛ "f" ⇒ ƛ "x" ⇒ ` "f" · (` "f" · ` "x") ``
* `` ƛ "sam" ⇒ ƛ "zelda" ⇒ ` "sam" · (` "sam" · ` "zelda") ``
* `` ƛ "z" ⇒ ƛ "s" ⇒ ` "z" · (` "z" · ` "s") ``
* `` ƛ "😇" ⇒ ƛ "😈" ⇒ # "😇" · (# "😇" · # "😈" ) ``
are all considered equivalent. Following the convention introduced
@ -231,13 +232,13 @@ this equivalence relation is called _alpha renaming_.
As we descend from a term into its subterms, variables
that are bound may become free. Consider the following terms.
* `` ƛ "s" ⇒ ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋) ``
* `` ƛ "s" ⇒ ƛ "z" ⇒ ` "s" · (` "s" · ` "z") ``
has both `s` and `z` as bound variables.
* `` ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋) ``
* `` ƛ "z" ⇒ ` "s" · (` "s" · ` "z") ``
has `s` bound and `z` free.
* `` ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋) ``
* `` ` "s" · (` "s" · ` "z") ``
has both `s` and `z` as free variables.
We say that a term with no free variables is _closed_; otherwise it is
@ -247,12 +248,12 @@ two are open.
Different occurrences of a variable may be bound and free.
In the term
(ƛ "x" ⇒ ⌊ "x" ⌋) · ⌊ "x" ⌋
(ƛ "x" ⇒ ` "x") · ` "x"
the inner occurrence of `x` is bound while the outer occurrence is free.
By alpha renaming, the term above is equivalent to
(ƛ "y" ⇒ ⌊ "y" ⌋) · ⌊ "x" ⌋
(ƛ "y" ⇒ ` "y") · ` "x"
in which `y` is bound and `x` is free. A common convention, called the
_Barendregt convention_, is to use alpha renaming to ensure that the bound
@ -264,17 +265,17 @@ Case and recursion also introduce bound variables, which are also subject
to alpha renaming. In the term
μ "+" ⇒ ƛ "m" ⇒ ƛ "n" ⇒
`case ⌊ "m" ⌋
[zero⇒ ⌊ "n" ⌋
|suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋) ]
`case ` "m"
[zero⇒ ` "n"
|suc "m" ⇒ `suc (` "+" · ` "m" · ` "n") ]
notice that there are two binding occurrences of `m`, one in the first
line and one in the last line. It is equivalent to the following term,
μ "plus" ⇒ ƛ "x" ⇒ ƛ "y" ⇒
`case ⌊ "x" ⌋
[zero⇒ ⌊ "y" ⌋
|suc "x" ⇒ `suc (⌊ "plus" ⌋ · ⌊ "x" ⌋ · ⌊ "y" ⌋) ]
`case ` "x"
[zero⇒ ` "y"
|suc "x" ⇒ `suc (` "plus" · ` "x" · ` "y") ]
where the two binding occurrences corresponding to `m` now have distinct
names, `x` and `x`.
@ -342,13 +343,13 @@ Substitution plays a key role in defining the
operational semantics of function application.
For instance, we have
(ƛ "s" ⇒ ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋)) · sucᶜ · `zero
(ƛ "s" ⇒ ƛ "z" ⇒ ` "s" · (` "s" · ` "z")) · sucᶜ · `zero
(ƛ "z" ⇒ sucᶜ · (sucᶜ · "z")) · `zero
sucᶜ · (sucᶜ · `zero)
where we substitute `sucᶜ` for `` ⌊ "s" ⌋ `` and `` `zero `` for `` ⌊ "z" ⌋ ``
where we substitute `sucᶜ` for `` ` "s" `` and `` `zero `` for `` ` "z" ``
in the body of the function abstraction.
We write substitution as `N [ x := V ]`, meaning
@ -360,19 +361,19 @@ usually substitute values.
Here are some examples:
* `` (sucᶜ · (sucᶜ · ⌊ "z" ⌋)) [ "z" := `zero ] `` yields
* `` (sucᶜ · (sucᶜ · ` "z")) [ "z" := `zero ] `` yields
`` sucᶜ · (sucᶜ · `zero) ``
* `` (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋)) [ "s" := sucᶜ ] `` yields
ƛ "z" ⇒ sucᶜ · (sucᶜ · ⌊ "z" ⌋) ``
* `` (ƛ "x" ⇒ ⌊ "y" ⌋) [ "y" := `zero ] `` yields `` ƛ "x" ⇒ `zero ``
* `` (ƛ "x" ⇒ ⌊ "x" ⌋) [ "x" := `zero ] `` yields `` ƛ "x" ⇒ ⌊ "x" ⌋ ``
* `` (ƛ "y" ⇒ ⌊ "y" ⌋) [ "x" := `zero ] `` yields `` ƛ "x" ⇒ ⌊ "x" ⌋ ``
* `` (ƛ "z" ⇒ ` "s" · (` "s" · ` "z")) [ "s" := sucᶜ ] `` yields
ƛ "z" ⇒ sucᶜ · (sucᶜ · ` "z") ``
* `` (ƛ "x" ⇒ ` "y") [ "y" := `zero ] `` yields `` ƛ "x" ⇒ `zero ``
* `` (ƛ "x" ⇒ ` "x") [ "x" := `zero ] `` yields `` ƛ "x" ⇒ ` "x" ``
* `` (ƛ "y" ⇒ ` "y") [ "x" := `zero ] `` yields `` ƛ "x" ⇒ ` "x" ``
In the last but one example, substituting `` `zero `` for `x` in
`` ƛ "x" ⇒ ⌊ "x" ⌋ `` does _not_ yield `` ƛ "x" ⇒ `zero ``,
`` ƛ "x" ⇒ ` "x" `` does _not_ yield `` ƛ "x" ⇒ `zero ``,
since `x` is bound in the lambda abstraction.
The choice of bound names is irrelevant: both
`` ƛ "x" ⇒ ⌊ "x" ⌋ `` and `` ƛ "y" ⇒ ⌊ "y" ⌋ `` stand for the
`` ƛ "x" ⇒ ` "x" `` and `` ƛ "y" ⇒ ` "y" `` stand for the
identity function. One way to think of this is that `x` within
the body of the abstraction stands for a _different_ variable than
`x` outside the abstraction, they just happen to have the same name.
@ -382,13 +383,13 @@ when term substituted for the variable is closed. This is because
substitution by terms that are _not_ closed may require renaming
of bound variables. For example:
* `` (ƛ "x" ⇒ ⌊ "x" ⌋ · ⌊ "y" ⌋) [ "y" := ⌊ "x" ⌋ · ⌊ "y" ⌋ ] `` should not yield
`` ƛ "x" ⇒ ⌊ "x" ⌋ · (⌊ "x" ⌋ · ⌊ "y" ⌋) ``
* `` (ƛ "x" ⇒ ` "x" · ` "y") [ "y" := ` "x" · ` "y" ] `` should not yield
`` ƛ "x" ⇒ ` "x" · (` "x" · ` "y") ``
Instead, we should rename the variables to avoid capture.
* `` (ƛ "x" ⇒ ⌊ "x" ⌋ · ⌊ "y" ⌋) [ "y" := ⌊ "x" ⌋ · ⌊ "y" ⌋ ] `` should yield
`` ƛ "z" ⇒ ⌊ "z" ⌋ · (⌊ "x" ⌋ · ⌊ "y" ⌋) ``
* `` (ƛ "x" ⇒ ` "x" · ` "y") [ "y" := ` "x" · ` "y" ] `` should yield
`` ƛ "z" ⇒ ` "z" · (` "x" · ` "y") ``
Formal definition of substitution with suitable renaming is considerably
more complex, so we avoid it by restricting to substitution by closed terms,
@ -400,9 +401,9 @@ Here is the formal definition of substitution by closed terms in Agda.
infix 9 _[_:=_]
_[_:=_] : Term → Id → Term → Term
⌊ x ⌋ [ y := V ] with x ≟ y
(` x) [ y := V ] with x ≟ y
... | yes _ = V
... | no _ = ⌊ x ⌋
... | no _ = ` x
(ƛ x ⇒ N) [ y := V ] with x ≟ y
... | yes _ = ƛ x ⇒ N
... | no _ = ƛ x ⇒ (N [ y := V ])
@ -440,19 +441,19 @@ simply push substitution recursively into the subterms.
Here is confirmation that the examples above are correct.
\begin{code}
_ : (sucᶜ · sucᶜ · ⌊ "z" ⌋) [ "z" := `zero ] ≡ sucᶜ · sucᶜ · `zero
_ : (sucᶜ · sucᶜ · ` "z") [ "z" := `zero ] ≡ sucᶜ · sucᶜ · `zero
_ = refl
_ : (ƛ "z" ⇒ ⌊ "s" ⌋ · ⌊ "s" ⌋ · ⌊ "z" ⌋) [ "s" := sucᶜ ] ≡ ƛ "z" ⇒ sucᶜ · sucᶜ · ⌊ "z" ⌋
_ : (ƛ "z" ⇒ ` "s" · ` "s" · ` "z") [ "s" := sucᶜ ] ≡ ƛ "z" ⇒ sucᶜ · sucᶜ · ` "z"
_ = refl
_ : (ƛ "x" ⇒ ⌊ "y" ⌋) [ "y" := `zero ] ≡ ƛ "x" ⇒ `zero
_ : (ƛ "x" ⇒ ` "y") [ "y" := `zero ] ≡ ƛ "x" ⇒ `zero
_ = refl
_ : (ƛ "x" ⇒ ⌊ "x" ⌋) [ "x" := `zero ] ≡ ƛ "x" ⇒ ⌊ "x" ⌋
_ : (ƛ "x" ⇒ ` "x") [ "x" := `zero ] ≡ ƛ "x" ⇒ ` "x"
_ = refl
_ : (ƛ "y" ⇒ ⌊ "y" ⌋) [ "x" := `zero ] ≡ ƛ "y" ⇒ ⌊ "y" ⌋
_ : (ƛ "y" ⇒ ` "y") [ "x" := `zero ] ≡ ƛ "y" ⇒ ` "y"
_ = refl
\end{code}
@ -460,11 +461,11 @@ _ = refl
What is the result of the following substitution?
(ƛ "y" ⇒ ⌊ "x" ⌋ · (ƛ "x" ⇒ ⌊ "x" ⌋)) [ "x" := `zero ]
(ƛ "y" ⇒ ` "x" · (ƛ "x" ⇒ ` "x")) [ "x" := `zero ]
1. `` (ƛ "y" ⇒ ⌊ "x" ⌋ · (ƛ "x" ⇒ ⌊ "x" ⌋)) ``
2. `` (ƛ "y" ⇒ ⌊ "x" ⌋ · (ƛ "x" ⇒ `zero)) ``
3. `` (ƛ "y" ⇒ `zero · (ƛ "x" ⇒ ⌊ "x" ⌋)) ``
1. `` (ƛ "y" ⇒ ` "x" · (ƛ "x" ⇒ ` "x")) ``
2. `` (ƛ "y" ⇒ ` "x" · (ƛ "x" ⇒ `zero)) ``
3. `` (ƛ "y" ⇒ `zero · (ƛ "x" ⇒ ` "x")) ``
4. `` (ƛ "y" ⇒ `zero · (ƛ "x" ⇒ `zero)) ``
@ -479,16 +480,16 @@ the argument for the variable in the abstraction.
In an informal presentation of the operational semantics,
the rules for reduction of applications are written as follows.
L L
--------------- ξ·₁
L · M L · M
L L
-------------- ξ-·₁
L · M L · M
M M
--------------- ξ·₂
V · M V · M
M M
-------------- ξ-·₂
V · M V · M
--------------------------------- βλ·
(ƛ x ⇒ N) · V N [ x := V ]
---------------------------- β-ƛ
(ƛ x ⇒ N) · V N [ x := V ]
The Agda version of the rules below will be similar, except that universal
quantifications are made explicit, and so are the predicates that indicate
@ -513,75 +514,84 @@ the bound variable by the entire fixpoint term.
Here are the rules formalised in Agda.
\begin{code}
infix 4 __
infix 4 __
data __ : Term → Term → Set where
data __ : Term → Term → Set where
ξ-·₁ : ∀ {L L M}
→ L L
→ L L
-----------------
→ L · M L · M
→ L · M L · M
ξ-·₂ : ∀ {V M M}
→ Value V
→ M M
→ M M
-----------------
→ V · M V · M
→ V · M V · M
β-ƛ· : ∀ {x N V}
β-ƛ : ∀ {x N V}
→ Value V
------------------------------
→ (ƛ x ⇒ N) · V N [ x := V ]
→ (ƛ x ⇒ N) · V N [ x := V ]
ξ-suc : ∀ {M M}
→ M M
→ M M
------------------
→ `suc M `suc M
→ `suc M `suc M
ξ-case : ∀ {x L L M N}
→ L L
→ L L
-----------------------------------------------------------------
→ `case L [zero⇒ M |suc x ⇒ N ] `case L [zero⇒ M |suc x ⇒ N ]
→ `case L [zero⇒ M |suc x ⇒ N ] `case L [zero⇒ M |suc x ⇒ N ]
β-case-zero : ∀ {x M N}
β-zero : ∀ {x M N}
----------------------------------------
→ `case `zero [zero⇒ M |suc x ⇒ N ] M
→ `case `zero [zero⇒ M |suc x ⇒ N ] M
β-case-suc : ∀ {x V M N}
β-suc : ∀ {x V M N}
→ Value V
---------------------------------------------------
→ `case `suc V [zero⇒ M |suc x ⇒ N ] N [ x := V ]
→ `case `suc V [zero⇒ M |suc x ⇒ N ] N [ x := V ]
β-μ : ∀ {x M}
------------------------------
→ μ x ⇒ M M [ x := μ x ⇒ M ]
→ μ x ⇒ M M [ x := μ x ⇒ M ]
\end{code}
The reduction rules are carefully designed to ensure that subterms
of a term are reduced to values before the whole term is reduced.
This is referred to as _call by value_ reduction.
Further, we have arranged that subterms are reduced in a
left-to-right order. This means that reduction is _deterministic_:
for any term, there is at most one other term to which it reduces.
Put another way, our reduction relation `↦` is in fact a function.
#### Quiz
What does the following term step to?
(ƛ "x" ⇒ ⌊ "x" ⌋) · (ƛ "x" ⇒ ⌊ "x" ⌋) ⟶ ???
(ƛ "x" ⇒ ` "x") · (ƛ "x" ⇒ ` "x") ↦ ???
1. `` (ƛ "x" ⇒ ⌊ "x" ⌋) ``
2. `` (ƛ "x" ⇒ ⌊ "x" ⌋) · (ƛ "x" ⇒ ⌊ "x" ⌋) ``
3. `` (ƛ "x" ⇒ ⌊ "x" ⌋) · (ƛ "x" ⇒ ⌊ "x" ⌋) · (ƛ "x" ⇒ ⌊ "x" ⌋) ``
1. `` (ƛ "x" ⇒ ` "x") ``
2. `` (ƛ "x" ⇒ ` "x") · (ƛ "x" ⇒ ` "x") ``
3. `` (ƛ "x" ⇒ ` "x") · (ƛ "x" ⇒ ` "x") · (ƛ "x" ⇒ ` "x") ``
What does the following term step to?
(ƛ "x" ⇒ ⌊ "x" ⌋) · (ƛ "x" ⇒ ⌊ "x" ⌋) · (ƛ "x" ⇒ ⌊ "x" ⌋) ⟶ ???
(ƛ "x" ⇒ ` "x") · (ƛ "x" ⇒ ` "x") · (ƛ "x" ⇒ ` "x") ↦ ???
1. `` (ƛ "x" ⇒ ⌊ "x" ⌋) ``
2. `` (ƛ "x" ⇒ ⌊ "x" ⌋) · (ƛ "x" ⇒ ⌊ "x" ⌋) ``
3. `` (ƛ "x" ⇒ ⌊ "x" ⌋) · (ƛ "x" ⇒ ⌊ "x" ⌋) · (ƛ "x" ⇒ ⌊ "x" ⌋) ``
1. `` (ƛ "x" ⇒ ` "x") ``
2. `` (ƛ "x" ⇒ ` "x") · (ƛ "x" ⇒ ` "x") ``
3. `` (ƛ "x" ⇒ ` "x") · (ƛ "x" ⇒ ` "x") · (ƛ "x" ⇒ ` "x") ``
What does the following term step to? (Where `two` and `sucᶜ` are as defined above.)
two · sucᶜ · `zero ???
two · sucᶜ · `zero ???
1. `` sucᶜ · (sucᶜ · `zero) ``
2. `` (ƛ "z" ⇒ sucᶜ · (sucᶜ · ⌊ "z" ⌋)) · `zero ``
2. `` (ƛ "z" ⇒ sucᶜ · (sucᶜ · ` "z")) · `zero ``
3. `` `zero ``
@ -589,170 +599,155 @@ What does the following term step to? (Where `two` and `sucᶜ` are as defined
A single step is only part of the story. In general, we wish to repeatedly
step a closed term until it reduces to a value. We do this by defining
the reflexive and transitive closure `⟶*` of the step function `⟶`.
the reflexive and transitive closure `↠` of the step relation `↦`.
The reflexive and transitive closure `⟶*` of an arbitrary relation `⟶`
is the smallest relation that includes `⟶` and is also reflexive
and transitive. We could define this directly, as follows.
\begin{code}
module Closure (A : Set) (_⟶_ : A → A → Set) where
data _⟶*_ : A → A → Set where
refl : ∀ {M}
--------
→ M ⟶* M
trans : ∀ {L M N}
→ L ⟶* M
→ M ⟶* N
--------
→ L ⟶* N
inc : ∀ {M N}
→ M ⟶ N
--------
→ M ⟶* N
\end{code}
Here we use a module to define the reflexive and transitive
closure of an arbitrary relation.
The three clauses specify that `⟶*` is reflexive and transitive,
and that `⟶` implies `⟶*`.
However, it will prove more convenient to define the transitive
closure as a sequence of zero or more steps of the underlying
relation, along lines similar to that for reasoning about
chains of equalities
We define reflexive and transitive closure as a sequence of zero or
more steps of the underlying relation, along lines similar to that for
reasoning about chains of equalities
Chapter [Equality]({{ site.baseurl }}{% link out/plta/Equality.md %}).
\begin{code}
module Chain (A : Set) (_⟶_ : A → A → Set) where
infix 2 _↠_
infix 1 begin_
infixr 2 _↦⟨_⟩_
infix 3 _∎
infix 2 _⟶*_
infix 1 begin_
infixr 2 _⟶⟨_⟩_
infix 3 _∎
data _↠_ : Term → Term → Set where
_∎ : ∀ M
---------
→ M ↠ M
data _⟶*_ : A → A → Set where
_∎ : ∀ M
---------
→ M ⟶* M
_↦⟨_⟩_ : ∀ L {M N}
→ L ↦ M
→ M ↠ N
---------
→ L ↠ N
_⟶⟨_⟩_ : ∀ L {M N}
→ L ⟶ M
→ M ⟶* N
---------
→ L ⟶* N
begin_ : ∀ {M N} → (M ⟶* N) → (M ⟶* N)
begin M⟶*N = M⟶*N
begin_ : ∀ {M N} → (M ↠ N) → (M ↠ N)
begin M↠N = M↠N
\end{code}
We can read this as follows.
* From term `M`, we can take no steps,
giving a step of type `M ⟶* M`.
* From term `M`, we can take no steps, giving a step of type `M ↠ M`.
It is written `M ∎`.
* From term `L` we can take a single of type `L ⟶ M`
followed by zero or more steps of type `M ⟶* N`,
giving a step of type `L ⟶* N`,
It is written `L ⟨ L⟶M ⟩ M⟶*N`,
where `L⟶M` and `M⟶*N` are steps of the appropriate type.
* From term `L` we can take a single of type `L ↦ M` followed by zero
or more steps of type `M ↠ N`, giving a step of type `L ↠ N`. It is
written `L ↦⟨ L↦M ⟩ M↠N`, where `L↦M` and `M↠N` are steps of the
appropriate type.
The notation is chosen to allow us to lay
out example reductions in an appealing way,
as we will see in the next section.
The notation is chosen to allow us to lay out example reductions in an
appealing way, as we will see in the next section.
We then instantiate the second module to our specific notion
of reduction step.
As alternative is to define reflexive and transitive closure directly,
as the smallest relation that includes `↦` and is also reflexive
and transitive. We could do so as follows.
\begin{code}
open Chain (Term) (_⟶_)
data _↠_ : Term → Term → Set where
step : ∀ {M N}
→ M ↦ N
------
→ M ↠′ N
refl : ∀ {M}
------
→ M ↠′ M
trans : ∀ {L M N}
→ L ↠′ M
→ M ↠′ N
------
→ L ↠′ N
\end{code}
The three constructors specify, respectively, that `↠` includes `↦`
and is reflexive and transitive.
It is a straightforward exercise to show the two are equivalent.
#### Exercise (`closure-equivalent`)
#### Exercise (`↠≃↠′`)
Show that the two notions of reflexive and transitive closure
above are equivalent.
above are isomorphic.
## Examples
Here is a sample reduction demonstrating that two plus two is four.
\begin{code}
_ : four ⟶* `suc `suc `suc `suc `zero
_ : four `suc `suc `suc `suc `zero
_ =
begin
plus · two · two
⟨ ξ-·₁ (ξ-·₁ β-μ) ⟩
⟨ ξ-·₁ (ξ-·₁ β-μ) ⟩
(ƛ "m" ⇒ ƛ "n" ⇒
`case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (plus · ⌊ "m" ⌋ · ⌊ "n" ⌋) ])
`case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (plus · ` "m" · ` "n") ])
· two · two
⟶⟨ ξ-·₁ (β-ƛ· (V-suc (V-suc V-zero))) ⟩
↦⟨ ξ-·₁ (β-ƛ (V-suc (V-suc V-zero))) ⟩
(ƛ "n" ⇒
`case two [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (plus · ⌊ "m" ⌋ · ⌊ "n" ⌋) ])
`case two [zero⇒ ` "n" |suc "m" ⇒ `suc (plus · ` "m" · ` "n") ])
· two
⟶⟨ β-ƛ· (V-suc (V-suc V-zero)) ⟩
`case two [zero⇒ two |suc "m" ⇒ `suc (plus · ⌊ "m" ⌋ · two) ]
⟶⟨ β-case-suc (V-suc V-zero) ⟩
↦⟨ β-ƛ (V-suc (V-suc V-zero)) ⟩
`case two [zero⇒ two |suc "m" ⇒ `suc (plus · ` "m" · two) ]
↦⟨ β-suc (V-suc V-zero) ⟩
`suc (plus · `suc `zero · two)
⟨ ξ-suc (ξ-·₁ (ξ-·₁ β-μ)) ⟩
⟨ ξ-suc (ξ-·₁ (ξ-·₁ β-μ)) ⟩
`suc ((ƛ "m" ⇒ ƛ "n" ⇒
`case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (plus · ⌊ "m" ⌋ · ⌊ "n" ⌋) ])
`case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (plus · ` "m" · ` "n") ])
· `suc `zero · two)
⟶⟨ ξ-suc (ξ-·₁ (β-ƛ· (V-suc V-zero))) ⟩
↦⟨ ξ-suc (ξ-·₁ (β-ƛ (V-suc V-zero))) ⟩
`suc ((ƛ "n" ⇒
`case `suc `zero [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (plus · ⌊ "m" ⌋ · ⌊ "n" ⌋) ])
`case `suc `zero [zero⇒ ` "n" |suc "m" ⇒ `suc (plus · ` "m" · ` "n") ])
· two)
⟶⟨ ξ-suc (β-ƛ· (V-suc (V-suc V-zero))) ⟩
`suc (`case `suc `zero [zero⇒ two |suc "m" ⇒ `suc (plus · ⌊ "m" ⌋ · two) ])
⟶⟨ ξ-suc (β-case-suc V-zero) ⟩
↦⟨ ξ-suc (β-ƛ (V-suc (V-suc V-zero))) ⟩
`suc (`case `suc `zero [zero⇒ two |suc "m" ⇒ `suc (plus · ` "m" · two) ])
↦⟨ ξ-suc (β-suc V-zero) ⟩
`suc `suc (plus · `zero · two)
⟨ ξ-suc (ξ-suc (ξ-·₁ (ξ-·₁ β-μ))) ⟩
⟨ ξ-suc (ξ-suc (ξ-·₁ (ξ-·₁ β-μ))) ⟩
`suc `suc ((ƛ "m" ⇒ ƛ "n" ⇒
`case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (plus · ⌊ "m" ⌋ · ⌊ "n" ⌋) ])
`case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (plus · ` "m" · ` "n") ])
· `zero · two)
⟶⟨ ξ-suc (ξ-suc (ξ-·₁ (β-ƛ· V-zero))) ⟩
↦⟨ ξ-suc (ξ-suc (ξ-·₁ (β-ƛ V-zero))) ⟩
`suc `suc ((ƛ "n" ⇒
`case `zero [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (plus · ⌊ "m" ⌋ · ⌊ "n" ⌋) ])
`case `zero [zero⇒ ` "n" |suc "m" ⇒ `suc (plus · ` "m" · ` "n") ])
· two)
⟶⟨ ξ-suc (ξ-suc (β-ƛ· (V-suc (V-suc V-zero)))) ⟩
`suc `suc (`case `zero [zero⇒ two |suc "m" ⇒ `suc (plus · ⌊ "m" ⌋ · two) ])
⟶⟨ ξ-suc (ξ-suc β-case-zero) ⟩
↦⟨ ξ-suc (ξ-suc (β-ƛ (V-suc (V-suc V-zero)))) ⟩
`suc `suc (`case `zero [zero⇒ two |suc "m" ⇒ `suc (plus · ` "m" · two) ])
↦⟨ ξ-suc (ξ-suc β-zero) ⟩
`suc (`suc (`suc (`suc `zero)))
\end{code}
And here is a similar sample reduction for Church numerals.
\begin{code}
_ : fourᶜ ⟶* `suc `suc `suc `suc `zero
_ : fourᶜ `suc `suc `suc `suc `zero
_ =
begin
(ƛ "m" ⇒ ƛ "n" ⇒ ƛ "s" ⇒ ƛ "z" ⇒ ⌊ "m" ⌋ · ⌊ "s" ⌋ · (⌊ "n" ⌋ · ⌊ "s" ⌋ · ⌊ "z" ⌋))
(ƛ "m" ⇒ ƛ "n" ⇒ ƛ "s" ⇒ ƛ "z" ⇒ ` "m" · ` "s" · (` "n" · ` "s" · ` "z"))
· twoᶜ · twoᶜ · sucᶜ · `zero
⟶⟨ ξ-·₁ (ξ-·₁ (ξ-·₁ (β-ƛ· V-ƛ))) ⟩
(ƛ "n" ⇒ ƛ "s" ⇒ ƛ "z" ⇒ twoᶜ · ⌊ "s" ⌋ · (⌊ "n" ⌋ · ⌊ "s" ⌋ · ⌊ "z" ⌋))
↦⟨ ξ-·₁ (ξ-·₁ (ξ-·₁ (β-ƛ V-ƛ))) ⟩
(ƛ "n" ⇒ ƛ "s" ⇒ ƛ "z" ⇒ twoᶜ · ` "s" · (` "n" · ` "s" · ` "z"))
· twoᶜ · sucᶜ · `zero
⟶⟨ ξ-·₁ (ξ-·₁ (β-ƛ· V-ƛ)) ⟩
(ƛ "s" ⇒ ƛ "z" ⇒ twoᶜ · ⌊ "s" ⌋ · (twoᶜ · ⌊ "s" ⌋ · ⌊ "z" ⌋)) · sucᶜ · `zero
⟶⟨ ξ-·₁ (β-ƛ· V-ƛ) ⟩
(ƛ "z" ⇒ twoᶜ · sucᶜ · (twoᶜ · sucᶜ · ⌊ "z" ⌋)) · `zero
⟶⟨ β-ƛ· V-zero ⟩
↦⟨ ξ-·₁ (ξ-·₁ (β-ƛ V-ƛ)) ⟩
(ƛ "s" ⇒ ƛ "z" ⇒ twoᶜ · ` "s" · (twoᶜ · ` "s" · ` "z")) · sucᶜ · `zero
↦⟨ ξ-·₁ (β-ƛ V-ƛ) ⟩
(ƛ "z" ⇒ twoᶜ · sucᶜ · (twoᶜ · sucᶜ · ` "z")) · `zero
↦⟨ β-ƛ V-zero ⟩
twoᶜ · sucᶜ · (twoᶜ · sucᶜ · `zero)
⟶⟨ ξ-·₁ (β-ƛ· V-ƛ) ⟩
(ƛ "z" ⇒ sucᶜ · (sucᶜ · ⌊ "z" ⌋)) · (twoᶜ · sucᶜ · `zero)
⟶⟨ ξ-·₂ V-ƛ (ξ-·₁ (β-ƛ· V-ƛ)) ⟩
(ƛ "z" ⇒ sucᶜ · (sucᶜ · ⌊ "z" ⌋)) · ((ƛ "z" ⇒ sucᶜ · (sucᶜ · ⌊ "z" ⌋)) · `zero)
⟶⟨ ξ-·₂ V-ƛ (β-ƛ· V-zero) ⟩
(ƛ "z" ⇒ sucᶜ · (sucᶜ · ⌊ "z" ⌋)) · (sucᶜ · (sucᶜ · `zero))
⟶⟨ ξ-·₂ V-ƛ (ξ-·₂ V-ƛ (β-ƛ· V-zero)) ⟩
(ƛ "z" ⇒ sucᶜ · (sucᶜ · ⌊ "z" ⌋)) · (sucᶜ · (`suc `zero))
⟶⟨ ξ-·₂ V-ƛ (β-ƛ· (V-suc V-zero)) ⟩
(ƛ "z" ⇒ sucᶜ · (sucᶜ · ⌊ "z" ⌋)) · (`suc `suc `zero)
⟶⟨ β-ƛ· (V-suc (V-suc V-zero)) ⟩
↦⟨ ξ-·₁ (β-ƛ V-ƛ) ⟩
(ƛ "z" ⇒ sucᶜ · (sucᶜ · ` "z")) · (twoᶜ · sucᶜ · `zero)
↦⟨ ξ-·₂ V-ƛ (ξ-·₁ (β-ƛ V-ƛ)) ⟩
(ƛ "z" ⇒ sucᶜ · (sucᶜ · ` "z")) · ((ƛ "z" ⇒ sucᶜ · (sucᶜ · ` "z")) · `zero)
↦⟨ ξ-·₂ V-ƛ (β-ƛ V-zero) ⟩
(ƛ "z" ⇒ sucᶜ · (sucᶜ · ` "z")) · (sucᶜ · (sucᶜ · `zero))
↦⟨ ξ-·₂ V-ƛ (ξ-·₂ V-ƛ (β-ƛ V-zero)) ⟩
(ƛ "z" ⇒ sucᶜ · (sucᶜ · ` "z")) · (sucᶜ · (`suc `zero))
↦⟨ ξ-·₂ V-ƛ (β-ƛ (V-suc V-zero)) ⟩
(ƛ "z" ⇒ sucᶜ · (sucᶜ · ` "z")) · (`suc `suc `zero)
↦⟨ β-ƛ (V-suc (V-suc V-zero)) ⟩
sucᶜ · (sucᶜ · `suc `suc `zero)
⟶⟨ ξ-·₂ V-ƛ (β-ƛ· (V-suc (V-suc V-zero))) ⟩
↦⟨ ξ-·₂ V-ƛ (β-ƛ (V-suc (V-suc V-zero))) ⟩
sucᶜ · (`suc `suc `suc `zero)
⟶⟨ β-ƛ· (V-suc (V-suc (V-suc V-zero))) ⟩
↦⟨ β-ƛ (V-suc (V-suc (V-suc V-zero))) ⟩
`suc (`suc (`suc (`suc `zero)))
\end{code}
@ -803,7 +798,7 @@ Thus,
* What is the type of the following term?
ƛ "s" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · `zero)
ƛ "s" ⇒ ` "s" · (` "s" · `zero)
1. `` (` ⇒ `) ⇒ (` ⇒ `) ``
2. `` (` ⇒ `) ⇒ ` ``
@ -816,7 +811,7 @@ Thus,
* What is the type of the following term?
(ƛ "s" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · `zero)) · sucᵐ
(ƛ "s" ⇒ ` "s" · (` "s" · `zero)) · sucᵐ
1. `` (` ⇒ `) ⇒ (` ⇒ `) ``
2. `` (` ⇒ `) ⇒ ` ``
@ -910,9 +905,9 @@ and indicates in context `Γ` that term `M` has type `A`.
Context `Γ` provides types for all the free variables in `M`.
For example
* `` ∅ , "s" ⦂ ` ⇒ ` , "z" ⦂ `⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋) ⦂ ` ``
* `` ∅ , "s" ⦂ ` ⇒ ` ⊢ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋)) ⦂ ` ⇒ ` ``
* `` ∅ ⊢ ƛ "s" ⇒ ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋)) ⦂ (` ⇒ `) ⇒ ` ⇒ ` ``
* `` ∅ , "s" ⦂ ` ⇒ ` , "z" ⦂ `` "s" · (` "s" · ` "z") ⦂ ` ``
* `` ∅ , "s" ⦂ ` ⇒ ` ⊢ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z")) ⦂ ` ⇒ ` ``
* `` ∅ ⊢ ƛ "s" ⇒ ƛ "z" ⇒ ` "s" · (` "s" · ` "z")) ⦂ (` ⇒ `) ⇒ ` ⇒ ` ``
Typing is formalised as follows.
\begin{code}
@ -923,7 +918,7 @@ data _⊢_⦂_ : Context → Term → Type → Set where
Ax : ∀ {Γ x A}
→ Γ ∋ x ⦂ A
-------------
→ Γ ⊢ ⌊ x ⌋ ⦂ A
→ Γ ⊢ ` x ⦂ A
-- ⇒-I
⊢ƛ : ∀ {Γ x N A B}
@ -998,7 +993,7 @@ Here `_≟_` is the function that tests two identifiers for equality.
We intend to apply the function only when the
two arguments are indeed unequal, and indicate that the second
case should never arise by postulating a term `impossible` of
with the empty type `⊥`. If we use ^C ^N to normalise the term
with the empty type `⊥`. If we use `C `N to normalise the term
"a" ≠ "a"
@ -1016,17 +1011,17 @@ evidence of _any_ proposition whatsoever, regardless of its truth.
Type derivations correspond to trees. In informal notation, here
is a type derivation for the Church numberal two:
∋s ∋s ∋z
------------------- ⌊_⌋ ------------------- ⌊_⌋ --------------- ⌊_⌋
Γ₂ ⊢ ⌊ "s" ⌋ ⦂ A ⇒ A Γ₂ ⊢ ⌊ "s" ⌋ ⦂ A ⇒ A Γ₂ ⊢ ⌊ "z" ⌋ ⦂ A
------------------- ⌊_⌋ ------------------------------------------ _·_
Γ₂ ⊢ ⌊ "s" ⌋ ⦂ A ⇒ A Γ₂ ⊢ ⌊ "s" ⌋ · ⌊ "z" ⌋ ⦂ A
∋s ∋s ∋z
------------------- `_ ------------------- `_ --------------- `_
Γ₂ ⊢ ` "s" ⦂ A ⇒ A Γ₂ ⊢ ` "s" ⦂ A ⇒ A Γ₂ ⊢ ` "z" ⦂ A
------------------- `_ ------------------------------------------ _·_
Γ₂ ⊢ ` "s" ⦂ A ⇒ A Γ₂ ⊢ ` "s" · ` "z" ⦂ A
-------------------------------------------------- _·_
Γ₂ ⊢ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋) ⦂ A
Γ₂ ⊢ ` "s" · (` "s" · ` "z") ⦂ A
---------------------------------------------- ⊢ƛ
Γ₁ ⊢ ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋) ⦂ A ⇒ A
Γ₁ ⊢ ƛ "z" ⇒ ` "s" · (` "s" · ` "z") ⦂ A ⇒ A
---------------------------------------------------------- ⊢ƛ
∅ ⊢ ƛ "s" ⇒ ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋) ⦂ A ⇒ A
∅ ⊢ ƛ "s" ⇒ ƛ "z" ⇒ ` "s" · (` "s" · ` "z") ⦂ A ⇒ A
where `∋s` and `∋z` abbreviate the two derivations:
@ -1113,12 +1108,12 @@ the outermost term in `sucᶜ` in `⊢ƛ`, which is typed using `ƛ`. The
`ƛ` rule in turn takes one argument, which Agda leaves as a hole.
⊢sucᶜ = ⊢ƛ { }1
?1 : ∅ , "n" ⦂ ` ⊢ `suc ⌊ "n" ⌋ ⦂ `
?1 : ∅ , "n" ⦂ ` ⊢ `suc ` "n" ⦂ `
We can fill in the hole by type C-c C-r again.
⊢sucᶜ = ⊢ƛ (⊢suc { }2)
?2 : ∅ , "n" ⦂ `⌊ "n" ⌋ ⦂ `
?2 : ∅ , "n" ⦂ `` "n" ⦂ `
And again.
@ -1157,10 +1152,10 @@ the term `ƛ "x" ⇒ "x"` has type `A ⇒ A` for any type `A`.
### Non-examples
We can also show that terms are _not_ typeable. For example, here is
a formal proof that it is not possible to type the term `` `zero ·
`suc `zero ``. In other words, no type `A` is the type of this term. It
cannot be typed, because doing so requires that the first term in the
application is both a natural and a function.
a formal proof that it is not possible to type the term
`` `zero · `suc `zero ``. It cannot be typed, because doing so
requires that the first term in the application is both a natural and
a function.
\begin{code}
nope₁ : ∀ {A} → ¬ (∅ ⊢ `zero · `suc `zero ⦂ A)
@ -1168,11 +1163,11 @@ nope₁ (() · _)
\end{code}
As a second example, here is a formal proof that it is not possible to
type `` ƛ "x" ⇒ ⌊ "x" ⌋ · ⌊ "x" ⌋ `` It cannot be typed, because
type `` ƛ "x" ⇒ ` "x" · ` "x" `` It cannot be typed, because
doing so requires types `A` and `B` such that `A ⇒ B ≡ A`.
\begin{code}
nope₂ : ∀ {A} → ¬ (∅ ⊢ ƛ "x" ⇒ ⌊ "x" ⌋ · ⌊ "x" ⌋ ⦂ A)
nope₂ : ∀ {A} → ¬ (∅ ⊢ ƛ "x" ⇒ ` "x" · ` "x" ⦂ A)
nope₂ (⊢ƛ (Ax ∋x · Ax ∋x)) = contradiction (∋-injective ∋x ∋x)
where
contradiction : ∀ {A B} → ¬ (A ⇒ B ≡ A)
@ -1185,15 +1180,15 @@ nope₂ (⊢ƛ (Ax ∋x · Ax ∋x)) = contradiction (∋-injective ∋x
For each of the following, given a type `A` for which it is derivable,
or explain why there is no such `A`.
1. `` ∅ , "y" ⦂ ` ⇒ ` , "x" ⦂ `⌊ "y" ⌋ · ⌊ "x" ⌋ ⦂ A ``
2. `` ∅ , "y" ⦂ ` ⇒ ` , "x" ⦂ `⌊ "x" ⌋ · ⌊ "y" ⌋ ⦂ A ``
3. `` ∅ , "y" ⦂ ` ⇒ ` ⊢ ƛ "x" ⇒ ⌊ "y" ⌋ · ⌊ "x" ⌋ ⦂ A ``
1. `` ∅ , "y" ⦂ ` ⇒ ` , "x" ⦂ `` "y" · ` "x" ⦂ A ``
2. `` ∅ , "y" ⦂ ` ⇒ ` , "x" ⦂ `` "x" · ` "y" ⦂ A ``
3. `` ∅ , "y" ⦂ ` ⇒ ` ⊢ ƛ "x" ⇒ ` "y" · ` "x" ⦂ A ``
For each of the following, give type `A`, `B`, and `C` for which it is derivable,
or explain why there are no such types.
1. `` ∅ , "x" ⦂ A ⊢ ⌊ "x" ⌋ · ⌊ "x" ⌋ ⦂ B ``
2. `` ∅ , "x" ⦂ A , "y" ⦂ B ⊢ ƛ "z" ⇒ ⌊ "x" ⌋ · (⌊ "y" ⌋ · ⌊ "z" ⌋) ⦂ C ``
1. `` ∅ , "x" ⦂ A ⊢ ` "x" · ` "x" ⦂ B ``
2. `` ∅ , "x" ⦂ A , "y" ⦂ B ⊢ ƛ "z" ⇒ ` "x" · (` "y" · ` "z") ⦂ C ``
#### Exercise (`mul-type`)
@ -1211,7 +1206,8 @@ This chapter uses the following unicode
· U+00B7: MIDDLE DOT (\cdot)
😇 U+1F607: SMILING FACE WITH HALO
😈 U+1F608: SMILING FACE WITH HORNS
⟶ U+27F9: LONG RIGHTWARDS ARROW (\r5, \-->)
↦ U+21A6: RIGHTWARDS ARROW FROM BAR (\mapsto, \r-|)
↠ U+21A0: RIGHTWARDS TWO HEADED ARROW (\rr-)
ξ U+03BE: GREEK SMALL LETTER XI (\Gx or \xi)
β U+03B2: GREEK SMALL LETTER BETA (\Gb or \beta)
∋ U+220B: CONTAINS AS MEMBER (\ni)

View file

@ -15,7 +15,7 @@ Those parts will be revised.]
The last chapter formalised simply-typed lambda calculus and
introduced several important relations over it.
We write `Value M` if term `M` is a value.
We write `M N` if term `M` reduces to term `N`.
We write `M N` if term `M` reduces to term `N`.
And we write `Γ ⊢ M ⦂ A` if in context `Γ` the term `M` has type `A`.
We are particularly concerned with terms typed in the empty context
`∅`, which must be _closed_ (that is, have no _free variables_).
@ -40,7 +40,7 @@ a reduction step. As we will see, this property does _not_ hold for
every term, but it does hold for every closed, well-typed term.
_Progress_: If `∅ ⊢ M ⦂ A` then either `M` is a value or there is an `N` such
that `M N`.
that `M N`.
So, either we have a value, and we are done, or we can take a reduction step.
In the latter case, we would like to apply progress again. But first we need
@ -48,7 +48,7 @@ to know that the term yielded by the reduction is itself closed and well-typed.
It turns out that this property holds whenever we start with a closed,
well-typed term.
_Preservation_: If `∅ ⊢ M ⦂ A` and `M N` then `∅ ⊢ N ⦂ A`.
_Preservation_: If `∅ ⊢ M ⦂ A` and `M N` then `∅ ⊢ N ⦂ A`.
This gives us a recipe for evaluation. Start with a closed and well-typed term.
By progress, it is either a value, in which case we are done, or it reduces
@ -87,7 +87,6 @@ open import Relation.Nullary using (¬_; Dec; yes; no)
open import Function using (_∘_)
open import plta.Isomorphism
open import plta.Lambda
open Chain (Term) (_⟶_)
\end{code}
@ -192,7 +191,7 @@ second has a free variable. Every term that is well-typed and closed
has the desired property.
_Progress_: If `∅ ⊢ M ⦂ A` then either `M` is a value or there is an `N` such
that `M N`.
that `M N`.
To formulate this property, we first introduce a relation that
captures what it means for a term `M` to make progess.
@ -200,7 +199,7 @@ captures what it means for a term `M` to make progess.
data Progress (M : Term) : Set where
step : ∀ {N}
→ M N
→ M N
----------
→ Progress M
@ -210,7 +209,7 @@ data Progress (M : Term) : Set where
→ Progress M
\end{code}
A term `M` makes progress if either it can take a step, meaning there
exists a term `N` such that `M N`, or if it is done, meaning that
exists a term `N` such that `M N`, or if it is done, meaning that
`M` is a value.
If a term is well-typed in the empty context then it is a value.
@ -220,23 +219,23 @@ progress : ∀ {M A}
----------
→ Progress M
progress (Ax ())
progress (⊢ƛ ⊢N) = done V-ƛ
progress (⊢ƛ ⊢N) = done V-ƛ
progress (⊢L · ⊢M) with progress ⊢L
... | step L⟶L = step (ξ-·₁ L⟶L)
... | step L↦L = step (ξ-·₁ L↦L)
... | done VL with progress ⊢M
... | step M⟶M = step (ξ-·₂ VL M⟶M)
... | step M↦M = step (ξ-·₂ VL M↦M)
... | done VM with canonical ⊢L VL
... | C-ƛ _ = step (β-ƛ· VM)
progress ⊢zero = done V-zero
... | C-ƛ _ = step (β-ƛ VM)
progress ⊢zero = done V-zero
progress (⊢suc ⊢M) with progress ⊢M
... | step M⟶M = step (ξ-suc M⟶M)
... | done VM = done (V-suc VM)
... | step M↦M = step (ξ-suc M↦M)
... | done VM = done (V-suc VM)
progress (⊢case ⊢L ⊢M ⊢N) with progress ⊢L
... | step L⟶L = step (ξ-case L⟶L)
... | step L↦L = step (ξ-case L↦L)
... | done VL with canonical ⊢L VL
... | C-zero = step β-case-zero
... | C-suc CL = step (β-case-suc (value CL))
progress (⊢μ ⊢M) = step β-μ
... | C-zero = step β-zero
... | C-suc CL = step (β-suc (value CL))
progress (⊢μ ⊢M) = step β-μ
\end{code}
We induct on the evidence that `M` is well-typed.
Let's unpack the first three cases.
@ -249,7 +248,7 @@ Let's unpack the first three cases.
* If the term is an application `L · M`, recursively apply
progress to the derivation that `L` is well-typed.
+ If the term steps, we have evidence that `L L`,
+ If the term steps, we have evidence that `L L`,
which by `ξ-·₁` means that our original term steps
to `L · M`
@ -257,7 +256,7 @@ Let's unpack the first three cases.
a value. Recursively apply progress to the derivation
that `M` is well-typed.
- If the term steps, we have evidence that `M M`,
- If the term steps, we have evidence that `M M`,
which by `ξ-·₂` means that our original term steps
to `L · M`. Step `ξ-·₂` applies only if we have
evidence that `L` is a value, but progress on that
@ -269,7 +268,7 @@ Let's unpack the first three cases.
since we are in an application leads to the
conclusion that `L` must be a lambda
abstraction. We also have evidence that `M` is
a value, so our original term steps by `β-ƛ·`.
a value, so our original term steps by `β-ƛ`.
The remaining cases are similar. If by induction we have a
`step` case we apply a `ξ` rule, and if we have a `done` case
@ -289,11 +288,11 @@ Instead of defining a data type for `Progress M`, we could
have formulated progress using disjunction and existentials:
\begin{code}
postulate
progress : ∀ M {A} → ∅ ⊢ M ⦂ A → Value M ⊎ ∃[ N ](M N)
progress : ∀ M {A} → ∅ ⊢ M ⦂ A → Value M ⊎ ∃[ N ](M N)
\end{code}
This leads to a less perspicous proof. Instead of the mnemonic `done`
and `step` we use `inj₁` and `inj₂`, and the term `N` is no longer
implicit and so must be written out in full. In the case for `β-ƛ·`
implicit and so must be written out in full. In the case for `β-ƛ`
this requires that we match against the lambda expression `L` to
determine its bound variable and body, `ƛ x ⇒ N`, so we can show that
`L · M` reduces to `N [ x := M ]`.
@ -305,7 +304,7 @@ proof of `progress` above.
#### Exercise (`Progress-iso`)
Show that `Progress M` is isomorphic to `Value M ⊎ ∃[ N ](M N)`.
Show that `Progress M` is isomorphic to `Value M ⊎ ∃[ N ](M N)`.
## Prelude to preservation
@ -370,7 +369,7 @@ the same result as if we first substitute and then type the result.
The third step is to show preservation.
_Preservation_:
If `∅ ⊢ M ⦂ A` and `M N` then `∅ ⊢ N ⦂ A`.
If `∅ ⊢ M ⦂ A` and `M N` then `∅ ⊢ N ⦂ A`.
The proof is by induction over the possible reductions, and
the substitution lemma is crucial in showing that each of the
@ -404,7 +403,6 @@ ext : ∀ {Γ Δ}
→ (∀ {x A} → Γ ∋ x ⦂ A → Δ ∋ x ⦂ A)
-----------------------------------------------------
→ (∀ {x y A B} → Γ , y ⦂ B ∋ x ⦂ A → Δ , y ⦂ B ∋ x ⦂ A)
ext ρ Z = Z
ext ρ (S x≢y ∋x) = S x≢y (ρ ∋x)
\end{code}
@ -595,9 +593,9 @@ Now that naming is resolved, let's unpack the first three cases.
* In the variable case, we must show
∅ ⊢ V ⦂ B
Γ , y ⦂ B ⊢ ⌊ x ⌋ ⦂ A
Γ , y ⦂ B ⊢ ` x ⦂ A
------------------------
Γ ⊢ ⌊ x ⌋ [ y := V ] ⦂ A
Γ ⊢ ` x [ y := V ] ⦂ A
where the second hypothesis follows from:
@ -645,7 +643,7 @@ Now that naming is resolved, let's unpack the first three cases.
x ≢ y
Γ ∋ x ⦂ A
-------------
Γ ⊢ ⌊ x ⌋ ⦂ A
Γ ⊢ ` x ⦂ A
which follows by the typing rule for variables.
@ -735,20 +733,20 @@ that reduction preserves types is straightforward.
\begin{code}
preserve : ∀ {M N A}
→ ∅ ⊢ M ⦂ A
→ M N
→ M N
----------
→ ∅ ⊢ N ⦂ A
preserve (Ax ())
preserve (⊢ƛ ⊢N) ()
preserve (⊢L · ⊢M) (ξ-·₁ L⟶L) = (preserve ⊢L L⟶L) · ⊢M
preserve (⊢L · ⊢M) (ξ-·₂ VL M⟶M) = ⊢L · (preserve ⊢M M⟶M)
preserve ((⊢ƛ ⊢N) · ⊢V) (β-ƛ· VV) = subst ⊢V ⊢N
preserve (⊢L · ⊢M) (ξ-·₁ L↦L) = (preserve ⊢L L↦L) · ⊢M
preserve (⊢L · ⊢M) (ξ-·₂ VL M↦M) = ⊢L · (preserve ⊢M M↦M)
preserve ((⊢ƛ ⊢N) · ⊢V) (β-ƛ VV) = subst ⊢V ⊢N
preserve ⊢zero ()
preserve (⊢suc ⊢M) (ξ-suc M⟶M) = ⊢suc (preserve ⊢M M⟶M)
preserve (⊢case ⊢L ⊢M ⊢N) (ξ-case L⟶L) = ⊢case (preserve ⊢L L⟶L) ⊢M ⊢N
preserve (⊢case ⊢zero ⊢M ⊢N) β-case-zero = ⊢M
preserve (⊢case (⊢suc ⊢V) ⊢M ⊢N) (β-case-suc VV) = subst ⊢V ⊢N
preserve (⊢μ ⊢M) (β-μ) = subst (⊢μ ⊢M) ⊢M
preserve (⊢suc ⊢M) (ξ-suc M↦M) = ⊢suc (preserve ⊢M M↦M)
preserve (⊢case ⊢L ⊢M ⊢N) (ξ-case L↦L) = ⊢case (preserve ⊢L L↦L) ⊢M ⊢N
preserve (⊢case ⊢zero ⊢M ⊢N) β-zero = ⊢M
preserve (⊢case (⊢suc ⊢V) ⊢M ⊢N) (β-suc VV) = subst ⊢V ⊢N
preserve (⊢μ ⊢M) (β-μ) = subst (⊢μ ⊢M) ⊢M
\end{code}
The proof never mentions the types of `M` or `N`,
so in what follows we choose type name as convenient.
@ -757,9 +755,9 @@ Let's unpack the cases for two of the reduction rules.
* Rule `ξ-·₁`. We have
L L
L L
----------------
L · M L · M
L · M L · M
where the left-hand side is typed by
@ -771,13 +769,13 @@ Let's unpack the cases for two of the reduction rules.
By induction, we have
Γ ⊢ L ⦂ A ⇒ B
L L
L L
--------------
Γ ⊢ L ⦂ A ⇒ B
from which the typing of the right-hand side follows immediately.
* Rule `β-ƛ·`. We have
* Rule `β-ƛ`. We have
Value V
----------------------------
@ -813,15 +811,17 @@ well-typed term to its value, if it has one.
Some terms may reduce forever. Here is a simple example.
\begin{code}
sucμ = μ "x" ⇒ `suc (` "x")
_ =
begin
μ "x" ⇒ `suc ⌊ "x" ⌋
⟨ β-μ ⟩
`suc (μ "x" ⇒ `suc ⌊ "x" ⌋)
⟨ ξ-suc β-μ ⟩
`suc `suc (μ "x" ⇒ `suc ⌊ "x" ⌋)
⟨ ξ-suc (ξ-suc β-μ) ⟩
`suc `suc `suc (μ "x" ⇒ `suc ⌊ "x" ⌋)
sucμ
⟨ β-μ ⟩
`suc sucμ
⟨ ξ-suc β-μ ⟩
`suc `suc sucμ
⟨ ξ-suc (ξ-suc β-μ) ⟩
`suc `suc `suc sucμ
-- ...
\end{code}
@ -871,7 +871,7 @@ well-typed and an indication of whether reduction finished.
data Steps (L : Term) (A : Type) : Set where
steps : ∀ {N}
→ L ⟶* N
→ L ↠ N
→ ∅ ⊢ N ⦂ A
→ Finished N
----------
@ -886,18 +886,18 @@ eval : ∀ {L A}
→ ∅ ⊢ L ⦂ A
---------
→ Steps L A
eval {L} (gas zero) ⊢L = steps (L ∎) ⊢L out-of-gas
eval {L} (gas zero) ⊢L = steps (L ∎) ⊢L out-of-gas
eval {L} (gas (suc m)) ⊢L with progress ⊢L
... | done VL = steps (L ∎) ⊢L (done VL)
... | step L⟶M with eval (gas m) (preserve ⊢L L⟶M)
... | steps M⟶*N ⊢N fin = steps (L ⟶⟨ L⟶M ⟩ M⟶*N) ⊢N fin
... | done VL = steps (L ∎) ⊢L (done VL)
... | step L↦M with eval (gas m) (preserve ⊢L L↦M)
... | steps M↠N ⊢N fin = steps (L ↦⟨ L↦M ⟩ M↠N) ⊢N fin
\end{code}
Let `L` be the name of the term we are reducing, and `⊢L` be the
evidence that `L` is well-typed. We consider the amount of gas
remaining. There are two possibilities.
* It is zero, so we stop early. We return the trivial reduction
sequence `L ⟶* L`, evidence that `L` is well-typed, and an
sequence `L L`, evidence that `L` is well-typed, and an
indication that we are out of gas.
* It is non-zero and after the next step we have `m` gas remaining.
@ -905,165 +905,187 @@ remaining. There are two possibilities.
are two possibilities.
+ Term `L` is a value, so we are done. We return the
trivial reduction sequence `L ⟶* L`, evidence that `L` is
trivial reduction sequence `L L`, evidence that `L` is
well-typed, and the evidence that `L` is a value.
+ Term `L` steps to another term `M`. Preservation provides
evidence that `M` is also well-typed, and we recursively invoke
`eval` on the remaining gas. The result is evidence that
`M ⟶* N`, together with evidence that `N` is well-typed and an
`M N`, together with evidence that `N` is well-typed and an
indication of whether reduction finished. We combine the evidence
that `L ⟶ M` and `M ⟶* N` to return evidence that `L ⟶* N`,
that `L ↦ M` and `M ↠ N` to return evidence that `L ↠ N`,
together with the other relevant evidence.
### Examples
We can now use Agda to compute the reduction sequence for two plus two
given in the preceding chapter.
We can now use Agda to compute the non-terminating reduction
sequence given earlier. First, we show that the term `sucμ`
is well-typed.
\begin{code}
⊢sucμ : ∅ ⊢ μ "x" ⇒ `suc ` "x" ⦂ `
⊢sucμ = ⊢μ (⊢suc (Ax ∋x))
where
∋x = Z
\end{code}
To show the first three steps of the infinite reduction
sequence, we evaluate with three steps worth of gas.
\begin{code}
_ : eval (gas 3) ⊢sucμ ≡
steps
(μ "x" ⇒ `suc ` "x" ↦⟨ β-μ ⟩
`suc (μ "x" ⇒ `suc ` "x") ↦⟨ ξ-suc β-μ ⟩
`suc (`suc (μ "x" ⇒ `suc ` "x")) ↦⟨ ξ-suc (ξ-suc β-μ) ⟩
`suc (`suc (`suc (μ "x" ⇒ `suc ` "x"))) ∎)
(⊢suc (⊢suc (⊢suc (⊢μ (⊢suc (Ax Z)))))) out-of-gas
_ = refl
\end{code}
Similarly, we can use Agda to compute the reduction sequence for two plus two
given in the preceding chapter. Supplying 100 steps of gas is more than enough.
\begin{code}
_ : eval (gas 100) ⊢four ≡
steps
((μ "+" ⇒
(ƛ "m" ⇒
(ƛ "n" ⇒
`case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋)
`case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n")
])))
· `suc (`suc `zero)
· `suc (`suc `zero)
⟶⟨ ξ-·₁ (ξ-·₁ β-μ) ⟩
⟨ ξ-·₁ (ξ-·₁ β-μ) ⟩
(ƛ "m" ⇒
(ƛ "n" ⇒
`case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒
`case ` "m" [zero⇒ ` "n" |suc "m" ⇒
`suc
((μ "+" ⇒
(ƛ "m" ⇒
(ƛ "n" ⇒
`case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋)
`case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n")
])))
· ⌊ "m" ⌋
· ⌊ "n" ⌋)
· ` "m"
· ` "n")
]))
· `suc (`suc `zero)
· `suc (`suc `zero)
⟶⟨ ξ-·₁ (β-ƛ· (V-suc (V-suc V-zero))) ⟩
↦⟨ ξ-·₁ (β-ƛ (V-suc (V-suc V-zero))) ⟩
(ƛ "n" ⇒
`case `suc (`suc `zero) [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒
`case `suc (`suc `zero) [zero⇒ ` "n" |suc "m" ⇒
`suc
((μ "+" ⇒
(ƛ "m" ⇒
(ƛ "n" ⇒
`case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋)
`case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n")
])))
· ⌊ "m" ⌋
· ⌊ "n" ⌋)
· ` "m"
· ` "n")
])
· `suc (`suc `zero)
⟶⟨ β-ƛ· (V-suc (V-suc V-zero)) ⟩
↦⟨ β-ƛ (V-suc (V-suc V-zero)) ⟩
`case `suc (`suc `zero) [zero⇒ `suc (`suc `zero) |suc "m" ⇒
`suc
((μ "+" ⇒
(ƛ "m" ⇒
(ƛ "n" ⇒
`case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋)
`case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n")
])))
· ⌊ "m" ⌋
· ` "m"
· `suc (`suc `zero))
]
⟶⟨ β-case-suc (V-suc V-zero) ⟩
↦⟨ β-suc (V-suc V-zero) ⟩
`suc
((μ "+" ⇒
(ƛ "m" ⇒
(ƛ "n" ⇒
`case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋)
`case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n")
])))
· `suc `zero
· `suc (`suc `zero))
⟨ ξ-suc (ξ-·₁ (ξ-·₁ β-μ)) ⟩
⟨ ξ-suc (ξ-·₁ (ξ-·₁ β-μ)) ⟩
`suc
((ƛ "m" ⇒
(ƛ "n" ⇒
`case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒
`case ` "m" [zero⇒ ` "n" |suc "m" ⇒
`suc
((μ "+" ⇒
(ƛ "m" ⇒
(ƛ "n" ⇒
`case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋)
`case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n")
])))
· ⌊ "m" ⌋
· ⌊ "n" ⌋)
· ` "m"
· ` "n")
]))
· `suc `zero
· `suc (`suc `zero))
⟶⟨ ξ-suc (ξ-·₁ (β-ƛ· (V-suc V-zero))) ⟩
↦⟨ ξ-suc (ξ-·₁ (β-ƛ (V-suc V-zero))) ⟩
`suc
((ƛ "n" ⇒
`case `suc `zero [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒
`case `suc `zero [zero⇒ ` "n" |suc "m" ⇒
`suc
((μ "+" ⇒
(ƛ "m" ⇒
(ƛ "n" ⇒
`case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋)
`case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n")
])))
· ⌊ "m" ⌋
· ⌊ "n" ⌋)
· ` "m"
· ` "n")
])
· `suc (`suc `zero))
⟶⟨ ξ-suc (β-ƛ· (V-suc (V-suc V-zero))) ⟩
↦⟨ ξ-suc (β-ƛ (V-suc (V-suc V-zero))) ⟩
`suc
`case `suc `zero [zero⇒ `suc (`suc `zero) |suc "m" ⇒
`suc
((μ "+" ⇒
(ƛ "m" ⇒
(ƛ "n" ⇒
`case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋)
`case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n")
])))
· ⌊ "m" ⌋
· ` "m"
· `suc (`suc `zero))
]
⟶⟨ ξ-suc (β-case-suc V-zero) ⟩
↦⟨ ξ-suc (β-suc V-zero) ⟩
`suc
(`suc
((μ "+" ⇒
(ƛ "m" ⇒
(ƛ "n" ⇒
`case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋)
`case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n")
])))
· `zero
· `suc (`suc `zero)))
⟨ ξ-suc (ξ-suc (ξ-·₁ (ξ-·₁ β-μ))) ⟩
⟨ ξ-suc (ξ-suc (ξ-·₁ (ξ-·₁ β-μ))) ⟩
`suc
(`suc
((ƛ "m" ⇒
(ƛ "n" ⇒
`case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒
`case ` "m" [zero⇒ ` "n" |suc "m" ⇒
`suc
((μ "+" ⇒
(ƛ "m" ⇒
(ƛ "n" ⇒
`case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋)
`case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n")
])))
· ⌊ "m" ⌋
· ⌊ "n" ⌋)
· ` "m"
· ` "n")
]))
· `zero
· `suc (`suc `zero)))
⟶⟨ ξ-suc (ξ-suc (ξ-·₁ (β-ƛ· V-zero))) ⟩
↦⟨ ξ-suc (ξ-suc (ξ-·₁ (β-ƛ V-zero))) ⟩
`suc
(`suc
((ƛ "n" ⇒
`case `zero [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒
`case `zero [zero⇒ ` "n" |suc "m" ⇒
`suc
((μ "+" ⇒
(ƛ "m" ⇒
(ƛ "n" ⇒
`case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋)
`case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n")
])))
· ⌊ "m" ⌋
· ⌊ "n" ⌋)
· ` "m"
· ` "n")
])
· `suc (`suc `zero)))
⟶⟨ ξ-suc (ξ-suc (β-ƛ· (V-suc (V-suc V-zero)))) ⟩
↦⟨ ξ-suc (ξ-suc (β-ƛ (V-suc (V-suc V-zero)))) ⟩
`suc
(`suc
`case `zero [zero⇒ `suc (`suc `zero) |suc "m" ⇒
@ -1071,21 +1093,21 @@ _ : eval (gas 100) ⊢four ≡
((μ "+" ⇒
(ƛ "m" ⇒
(ƛ "n" ⇒
`case ⌊ "m" ⌋ [zero⇒ ⌊ "n" ⌋ |suc "m" ⇒ `suc (⌊ "+" ⌋ · ⌊ "m" ⌋ · ⌊ "n" ⌋)
`case ` "m" [zero⇒ ` "n" |suc "m" ⇒ `suc (` "+" · ` "m" · ` "n")
])))
· ⌊ "m" ⌋
· ` "m"
· `suc (`suc `zero))
])
⟶⟨ ξ-suc (ξ-suc β-case-zero) ⟩ `suc (`suc (`suc (`suc `zero))) ∎)
↦⟨ ξ-suc (ξ-suc β-zero) ⟩ `suc (`suc (`suc (`suc `zero))) ∎)
(⊢suc (⊢suc (⊢suc (⊢suc ⊢zero))))
(done (V-suc (V-suc (V-suc (V-suc V-zero)))))
_ = refl
\end{code}
The example above was generated by using ^C ^N to normalise the
The example above was generated by using `C `N to normalise the
left-hand side of the equation and pasting in the result as the
right-hand side of the equation. The result was then edited to give
the example reduction of the previous chapter, by writing `plus`
and `two` in place of the corresponding terms and reformatting.
right-hand side of the equation. The example reduction of the
previous chapter was derived from this result, by writing `plus` and
`two` in place of their corresponding expansions and reformatting.
Similarly, can evaluate the corresponding term for Church numerals.
\begin{code}
@ -1093,88 +1115,73 @@ _ : eval (gas 100) ⊢fourᶜ ≡
steps
((ƛ "m" ⇒
(ƛ "n" ⇒
(ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "m" ⌋ · ⌊ "s" ⌋ · (⌊ "n" ⌋ · ⌊ "s" ⌋ · ⌊ "z" ⌋)))))
· (ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋)))
· (ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋)))
· (ƛ "n" ⇒ `suc ⌊ "n" ⌋)
(ƛ "s" ⇒ (ƛ "z" ⇒ ` "m" · ` "s" · (` "n" · ` "s" · ` "z")))))
· (ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z")))
· (ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z")))
· (ƛ "n" ⇒ `suc ` "n")
· `zero
⟶⟨ ξ-·₁ (ξ-·₁ (ξ-·₁ (β-ƛ· V-ƛ))) ⟩
↦⟨ ξ-·₁ (ξ-·₁ (ξ-·₁ (β-ƛ V-ƛ))) ⟩
(ƛ "n" ⇒
(ƛ "s" ⇒
(ƛ "z" ⇒
(ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋))) · ⌊ "s" ⌋ ·
(⌊ "n" ⌋ · ⌊ "s" ⌋ · ⌊ "z" ⌋))))
· (ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋)))
· (ƛ "n" ⇒ `suc ⌊ "n" ⌋)
(ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z"))) · ` "s" ·
(` "n" · ` "s" · ` "z"))))
· (ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z")))
· (ƛ "n" ⇒ `suc ` "n")
· `zero
⟶⟨ ξ-·₁ (ξ-·₁ (β-ƛ· V-ƛ)) ⟩
↦⟨ ξ-·₁ (ξ-·₁ (β-ƛ V-ƛ)) ⟩
(ƛ "s" ⇒
(ƛ "z" ⇒
(ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋))) · ⌊ "s" ⌋ ·
((ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋))) · ⌊ "s" ⌋ · ⌊ "z" ⌋)))
· (ƛ "n" ⇒ `suc ⌊ "n" ⌋)
(ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z"))) · ` "s" ·
((ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z"))) · ` "s" · ` "z")))
· (ƛ "n" ⇒ `suc ` "n")
· `zero
⟶⟨ ξ-·₁ (β-ƛ· V-ƛ) ⟩
↦⟨ ξ-·₁ (β-ƛ V-ƛ) ⟩
(ƛ "z" ⇒
(ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋))) · (ƛ "n" ⇒ `suc ⌊ "n" ⌋)
(ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z"))) · (ƛ "n" ⇒ `suc ` "n")
·
((ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋))) · (ƛ "n" ⇒ `suc ⌊ "n" ⌋)
· ⌊ "z" ⌋))
((ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z"))) · (ƛ "n" ⇒ `suc ` "n")
· ` "z"))
· `zero
⟶⟨ β-ƛ· V-zero ⟩
(ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋))) · (ƛ "n" ⇒ `suc ⌊ "n" ⌋)
↦⟨ β-ƛ V-zero ⟩
(ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z"))) · (ƛ "n" ⇒ `suc ` "n")
·
((ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋))) · (ƛ "n" ⇒ `suc ⌊ "n" ⌋)
((ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z"))) · (ƛ "n" ⇒ `suc ` "n")
· `zero)
⟶⟨ ξ-·₁ (β-ƛ· V-ƛ) ⟩
(ƛ "z" ⇒ (ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ((ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ⌊ "z" ⌋)) ·
((ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋))) · (ƛ "n" ⇒ `suc ⌊ "n" ⌋)
↦⟨ ξ-·₁ (β-ƛ V-ƛ) ⟩
(ƛ "z" ⇒ (ƛ "n" ⇒ `suc ` "n") · ((ƛ "n" ⇒ `suc ` "n") · ` "z")) ·
((ƛ "s" ⇒ (ƛ "z" ⇒ ` "s" · (` "s" · ` "z"))) · (ƛ "n" ⇒ `suc ` "n")
· `zero)
⟶⟨ ξ-·₂ V-ƛ (ξ-·₁ (β-ƛ· V-ƛ)) ⟩
(ƛ "z" ⇒ (ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ((ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ⌊ "z" ⌋)) ·
((ƛ "z" ⇒ (ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ((ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ⌊ "z" ⌋)) ·
↦⟨ ξ-·₂ V-ƛ (ξ-·₁ (β-ƛ V-ƛ)) ⟩
(ƛ "z" ⇒ (ƛ "n" ⇒ `suc ` "n") · ((ƛ "n" ⇒ `suc ` "n") · ` "z")) ·
((ƛ "z" ⇒ (ƛ "n" ⇒ `suc ` "n") · ((ƛ "n" ⇒ `suc ` "n") · ` "z")) ·
`zero)
⟶⟨ ξ-·₂ V-ƛ (β-ƛ· V-zero) ⟩
(ƛ "z" ⇒ (ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ((ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ⌊ "z" ⌋)) ·
((ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ((ƛ "n" ⇒ `suc ⌊ "n" ⌋) · `zero))
⟶⟨ ξ-·₂ V-ƛ (ξ-·₂ V-ƛ (β-ƛ· V-zero)) ⟩
(ƛ "z" ⇒ (ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ((ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ⌊ "z" ⌋)) ·
((ƛ "n" ⇒ `suc ⌊ "n" ⌋) · `suc `zero)
⟶⟨ ξ-·₂ V-ƛ (β-ƛ· (V-suc V-zero)) ⟩
(ƛ "z" ⇒ (ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ((ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ⌊ "z" ⌋)) ·
↦⟨ ξ-·₂ V-ƛ (β-ƛ V-zero) ⟩
(ƛ "z" ⇒ (ƛ "n" ⇒ `suc ` "n") · ((ƛ "n" ⇒ `suc ` "n") · ` "z")) ·
((ƛ "n" ⇒ `suc ` "n") · ((ƛ "n" ⇒ `suc ` "n") · `zero))
↦⟨ ξ-·₂ V-ƛ (ξ-·₂ V-ƛ (β-ƛ V-zero)) ⟩
(ƛ "z" ⇒ (ƛ "n" ⇒ `suc ` "n") · ((ƛ "n" ⇒ `suc ` "n") · ` "z")) ·
((ƛ "n" ⇒ `suc ` "n") · `suc `zero)
↦⟨ ξ-·₂ V-ƛ (β-ƛ (V-suc V-zero)) ⟩
(ƛ "z" ⇒ (ƛ "n" ⇒ `suc ` "n") · ((ƛ "n" ⇒ `suc ` "n") · ` "z")) ·
`suc (`suc `zero)
⟶⟨ β-ƛ· (V-suc (V-suc V-zero)) ⟩
(ƛ "n" ⇒ `suc ⌊ "n" ⌋) · ((ƛ "n" ⇒ `suc ⌊ "n" ⌋) · `suc (`suc `zero))
⟶⟨ ξ-·₂ V-ƛ (β-ƛ· (V-suc (V-suc V-zero))) ⟩
(ƛ "n" ⇒ `suc ⌊ "n" ⌋) · `suc (`suc (`suc `zero)) ⟶
β-ƛ· (V-suc (V-suc (V-suc V-zero))) ⟩
↦⟨ β-ƛ (V-suc (V-suc V-zero)) ⟩
(ƛ "n" ⇒ `suc ` "n") · ((ƛ "n" ⇒ `suc ` "n") · `suc (`suc `zero))
↦⟨ ξ-·₂ V-ƛ (β-ƛ (V-suc (V-suc V-zero))) ⟩
(ƛ "n" ⇒ `suc ` "n") · `suc (`suc (`suc `zero)) ↦
β-ƛ (V-suc (V-suc (V-suc V-zero))) ⟩
`suc (`suc (`suc (`suc `zero))) ∎)
(⊢suc (⊢suc (⊢suc (⊢suc ⊢zero))))
(done (V-suc (V-suc (V-suc (V-suc V-zero)))))
_ = refl
\end{code}
We can also derive the non-terminating example.
\begin{code}
⊢sucμ : ∅ ⊢ μ "x" ⇒ `suc ⌊ "x" ⌋ ⦂ `
⊢sucμ = ⊢μ (⊢suc (Ax ∋x))
where
∋x = Z
_ : eval (gas 3) ⊢sucμ ≡
steps
(μ "x" ⇒ `suc ⌊ "x" ⌋ Chain.⟶⟨ β-μ ⟩
`suc (μ "x" ⇒ `suc ⌊ "x" ⌋) Chain.⟶⟨ ξ-suc β-μ ⟩
`suc (`suc (μ "x" ⇒ `suc ⌊ "x" ⌋)) Chain.⟶⟨ ξ-suc (ξ-suc β-μ) ⟩
`suc (`suc (`suc (μ "x" ⇒ `suc ⌊ "x" ⌋))) Chain.∎)
(⊢suc (⊢suc (⊢suc (⊢μ (⊢suc (Ax Z)))))) out-of-gas
_ = refl
\end{code}
Again, the example in the previous section was derived by editing the
above.
#### Exercise `subject_expansion`
We say that `M` _reduces_ to `N` if `M N`,
and conversely that `M` _expands_ to `N` if `N M`.
We say that `M` _reduces_ to `N` if `M ↦ N`,
and conversely that `M` _expands_ to `N` if `N ↦ M`.
The preservation property is sometimes called _subject reduction_.
Its opposite is _subject expansion_, which holds if
`M ==> N` and `∅ ⊢ N ⦂ A` imply `∅ ⊢ M ⦂ A`.
@ -1186,7 +1193,7 @@ with case expressions and one not involving case expressions.
A term is _normal_ if it cannot reduce.
\begin{code}
Normal : Term → Set
Normal M = ∀ {N} → ¬ (M N)
Normal M = ∀ {N} → ¬ (M N)
\end{code}
A term is _stuck_ if it is normal yet not a value.
@ -1200,7 +1207,7 @@ Using progress and preservation, it is easy to show that well-typed terms don't
postulate
wttdgs : ∀ {M N A}
→ ∅ ⊢ M ⦂ A
→ M ⟶* N
→ M N
-----------
→ ¬ (Stuck M)
\end{code}
@ -1223,8 +1230,8 @@ unstuck : ∀ {M A}
→ ∅ ⊢ M ⦂ A
-----------
→ ¬ (Stuck M)
unstuck ⊢M ⟨ ¬MN , ¬VM ⟩ with progress ⊢M
... | step M⟶N = ¬M⟶N M⟶N
unstuck ⊢M ⟨ ¬MN , ¬VM ⟩ with progress ⊢M
... | step M↦N = ¬M↦N M↦N
... | done VM = ¬VM VM
\end{code}
@ -1232,21 +1239,21 @@ Any descendant of a well-typed term is well-typed.
\begin{code}
preserve* : ∀ {M N A}
→ ∅ ⊢ M ⦂ A
→ M ⟶* N
→ M N
---------
→ ∅ ⊢ N ⦂ A
preserve* ⊢M (M ∎) = ⊢M
preserve* ⊢L (L ⟶⟨ L⟶M ⟩ M⟶*N) = preserve* (preserve ⊢L L⟶M) M⟶*N
preserve* ⊢L (L ↦⟨ L↦M ⟩ M↠N) = preserve* (preserve ⊢L L↦M) M↠N
\end{code}
Combining the above gives us the desired result.
\begin{code}
wttdgs : ∀ {M N A}
→ ∅ ⊢ M ⦂ A
→ M ⟶* N
→ M N
-----------
→ ¬ (Stuck N)
wttdgs ⊢M M⟶*N = unstuck (preserve* ⊢M M⟶*N)
wttdgs ⊢M M↠N = unstuck (preserve* ⊢M M↠N)
\end{code}
@ -1261,7 +1268,7 @@ and preservation theorems for the simply typed lambda-calculus.
Suppose we add a new term `zap` with the following reduction rule
--------- β-zap
M zap
M zap
and the following typing rule:
@ -1286,10 +1293,10 @@ Suppose instead that we add a new term `foo` with the following
reduction rules:
--------------------- β-foo₁
(λ x ⇒ ⌊ x ⌋) ⟶ foo
(λ x ⇒ ` x) ↦ foo
------------ β-foo₂
foo zero
foo zero
Which of the following properties remain true in
the presence of this rule? For each one, write either
@ -1305,7 +1312,7 @@ false, give a counterexample.
#### Quiz
Suppose instead that we remove the rule `ξ·₁` from the `⟶`
Suppose instead that we remove the rule `ξ·₁` from the step
relation. Which of the following properties remain
true in the absence of this rule? For each one, write either
"remains true" or else "becomes false." If a property becomes