completed draft of PandP

This commit is contained in:
wadler 2018-06-28 17:50:46 -03:00
parent ec55c30779
commit 2c570407e4

View file

@ -853,28 +853,28 @@ data Gas : Set where
When our evaluator returns a term `N`, it will either give evidence that
`N` is a value or indicate that it ran out of gas.
\begin{code}
data Done? (N : Term) : Set where
data Finished (N : Term) : Set where
done :
Value N
-------
Done? N
----------
Finished N
out-of-gas :
-------
Done? N
----------
Finished N
\end{code}
Given a term `M` of type `A`, the evaluator will, for some `N`, return
a reduction sequence from `M` to `N` along with evidence that `N` is
well-typed and an indication of whether reduction completed.
Given a term `L` of type `A`, the evaluator will, for some `N`, return
a reduction sequence from `L` to `N` along with evidence that `N` is
well-typed and an indication of whether reduction finished.
\begin{code}
data Eval (M : Term) (A : Type) : Set where
data Steps (L : Term) (A : Type) : Set where
steps : ∀ {N}
M ⟶* N
L ⟶* N
→ ∅ ⊢ N ⦂ A
Done? N
--------
Eval M A
Finished N
----------
Steps L A
\end{code}
The evaluator takes gas and evidence that a term is well-typed,
and returns the result of evaluating that term for a number of
@ -884,12 +884,12 @@ eval : ∀ {L A}
→ Gas
→ ∅ ⊢ L ⦂ A
---------
Eval L A
eval {L} (gas zero) ⊢L = steps (L ∎) ⊢L out-of-gas
Steps L A
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 normalise (gas m) (preserve ⊢L L⟶M)
... | steps M⟶*N ⊢N done? = steps (L ⟶⟨ L⟶M ⟩ M⟶*N) ⊢N done?
... | 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
@ -909,51 +909,20 @@ remaining. There are two possibilities.
+ 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 will be another term
`N` such that `M ⟶* N` and `N` is well-typed plus an indication
of how reduction terminated. We combine the evidence that `L ⟶ M`
and `M ⟶* N` to return evidence that `L ⟶* N`, together with
the evidence that `N` is well-typed and the indication of how
reduction termination.
`eval` on the remaining gas. The result is evidence that
`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`,
together with the other relevant evidence.
\begin{code}
{-
data Normalise (M : Term) : Set where
out-of-gas : ∀ {N A}
→ M ⟶* N
→ ∅ ⊢ N ⦂ A
-------------
→ Normalise M
normal : ∀ {V}
→ Gas
→ M ⟶* V
→ Value V
--------------
→ Normalise M
normalise : ∀ {M A}
→ Gas
→ ∅ ⊢ M ⦂ A
-----------
→ Normalise M
normalise {L} zero ⊢L = out-of-gas (L ∎) ⊢L
normalise {L} (suc m) ⊢L with progress ⊢L
... | done VL = normal (suc m) (L ∎) VL
... | step L⟶M with normalise m (preserve ⊢L L⟶M)
... | out-of-gas M⟶*N ⊢N = out-of-gas (L ⟶⟨ L⟶M ⟩ M⟶*N) ⊢N
... | normal n M⟶*V VV = normal n (L ⟶⟨ L⟶M ⟩ M⟶*V) VV
-}
\end{code}
### Examples
We can now use Agda to compute the reduction sequence for two plus two
given in the preceding chapter.
\begin{code}
{-
_ : normalise 100 ⊢four ≡
normal 88
_ : eval (gas 100) ⊢four ≡
steps
((μ "+" ⇒
(ƛ "m" ⇒
(ƛ "n" ⇒
@ -1107,13 +1076,20 @@ _ : normalise 100 ⊢four ≡
· `suc (`suc `zero))
])
⟶⟨ ξ-suc (ξ-suc β-case-zero) ⟩ `suc (`suc (`suc (`suc `zero))) ∎)
(V-suc (V-suc (V-suc (V-suc V-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
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.
Similarly, can evaluate the corresponding term for Church numerals.
\begin{code}
_ : normalise 100 ⊢fourᶜ ≡
normal 88
_ : eval (gas 100) ⊢fourᶜ ≡
steps
((ƛ "m" ⇒
(ƛ "n" ⇒
(ƛ "s" ⇒ (ƛ "z" ⇒ ⌊ "m" ⌋ · ⌊ "s" ⌋ · (⌊ "n" ⌋ · ⌊ "s" ⌋ · ⌊ "z" ⌋)))))
@ -1172,89 +1148,126 @@ _ : normalise 100 ⊢fourᶜ ≡
(ƛ "n" ⇒ `suc ⌊ "n" ⌋) · `suc (`suc (`suc `zero)) ⟶⟨
β-ƛ· (V-suc (V-suc (V-suc V-zero))) ⟩
`suc (`suc (`suc (`suc `zero))) ∎)
(V-suc (V-suc (V-suc (V-suc V-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}
#### Exercise: 2 stars, recommended (subject_expansion_stlc)
<!--
An exercise in the [Types]({{ "Types" | relative_url }}) chapter asked about the
subject expansion property for the simple language of arithmetic and boolean
expressions. Does this property hold for STLC? That is, is it always the case
that, if `M ==> N` and `∅ ⊢ N ⦂ A`, then `∅ ⊢ M ⦂ A`? It is easy to find a
counter-example with conditionals, find one not involving conditionals.
-->
#### Exercise `subject_expansion`
We say that `M` _reduces_ to `N` if `M ⟶ N`,
and that `M` _expands_ to `N` if `N ⟶ M`.
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`, then `∅ ⊢ M ⦂ A`.
`M ==> N` and `∅ ⊢ N ⦂ A` imply `∅ ⊢ M ⦂ A`.
Find two counter-examples to subject expansion, one
with case expressions and one not involving case expressions.
## Type Soundness
#### Exercise: 2 stars, optional (type_soundness)
Put progress and preservation together and show that a well-typed
term can _never_ reach a stuck state.
## Well-typed terms don't get stuck
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.
\begin{code}
Stuck : Term → Set
Stuck M = Normal M × ¬ Value M
Stuck M = Normal M × ¬ Value M
\end{code}
Using progress and preservation, it is easy to show that well-typed terms don't get stuck.
\begin{code}
postulate
Soundness : ∀ {M N A}
wttdgs : ∀ {M N A}
→ ∅ ⊢ M ⦂ A
→ M ⟶* N
-----------
→ ¬ (Stuck N)
→ ¬ (Stuck M)
\end{code}
#### Exercise `stuck`
Give an example of a not well-typed term that does get stuck.
#### Exercise `wttdgs`
Show that if a term is well-typed it is not stuck,
and that any descendant of a well-typed term is also well-typed.
Combine these results to show `wttdgs`.
<div class="hidden">
If a term is well-typed, it does not get stuck.
\begin{code}
Soundness : ∀ {M N A}
unstuck : ∀ {M A}
→ ∅ ⊢ M ⦂ A
-----------
→ ¬ (Stuck M)
unstuck ⊢M ⟨ ¬M⟶N , ¬VM ⟩ with progress ⊢M
... | step M⟶N = ¬M⟶N M⟶N
... | done VM = ¬VM VM
\end{code}
Any descendant of a well-typed term is well-typed.
\begin{code}
preserve* : ∀ {M N A}
→ ∅ ⊢ M ⦂ A
→ M ⟶* N
---------
→ ∅ ⊢ N ⦂ A
preserve* ⊢M (M ∎) = ⊢M
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
-----------
→ ¬ (Stuck N)
Soundness ⊢M (M ∎) ⟨ ¬M⟶N , ¬VM ⟩ with progress ⊢M
... | step M⟶N = ¬M⟶N M⟶N
... | done VM = ¬VM VM
Soundness ⊢L (L ⟶⟨ L⟶M ⟩ M⟶*N) = Soundness (preserve ⊢L L⟶M) M⟶*N
wttdgs ⊢M M⟶*N = unstuck (preserve* ⊢M M⟶*N)
\end{code}
</div>
## Additional Exercises
#### Exercise: 1 star (progress_preservation_statement)
#### Exercise: `progress-preservation`
Without peeking at their statements above, write down the progress
and preservation theorems for the simply typed lambda-calculus.
#### Exercise: 2 stars (stlc_variation1)
#### Quiz
Suppose we add a new term `zap` with the following reduction rule
--------- (ST_Zap)
M ⟶ zap
--------- β-zap
M ⟶ zap
and the following typing rule:
----------- (T_Zap)
Γ ⊢ zap : A
----------- ⊢zap
Γ ⊢ zap ⦂ A
Which of the following properties of the STLC remain true in
Which of the following properties remain true in
the presence of these rules? For each property, write either
"remains true" or "becomes false." If a property becomes
false, give a counterexample.
@ -1266,18 +1279,18 @@ false, give a counterexample.
- Preservation
#### Exercise: 2 stars (stlc_variation2)
#### Quiz
Suppose instead that we add a new term `foo` with the following
reduction rules:
------------------- (Foo₁)
(λ x ⇒ ⌊ x ⌋) ⟶ foo
--------------------- β-foo₁
(λ x ⇒ ⌊ x ⌋) ⟶ foo
------------ (Foo₂)
foo ⟶ true
------------ β-foo₂
foo ⟶ zero
Which of the following properties of the STLC remain true in
Which of the following properties remain true in
the presence of this rule? For each one, write either
"remains true" or else "becomes false." If a property becomes
false, give a counterexample.
@ -1288,10 +1301,11 @@ false, give a counterexample.
- Preservation
#### Exercise: 2 stars (stlc_variation3)
#### Quiz
Suppose instead that we remove the rule `ξ·₁` from the `⟶`
relation. Which of the following properties of the STLC remain
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
false, give a counterexample.
@ -1302,14 +1316,28 @@ false, give a counterexample.
- Preservation
#### Exercise: 2 stars, optional (stlc_variation4)
Suppose instead that we add the following new rule to the
reduction relation:
---------------------------------------- (FunnyCaseZero)
case zero [zero⇒ M |suc x ⇒ N ] ⟶ true
#### Quiz
Which of the following properties of the STLC remain true in
We can enumerate all the computable function from naturals to
naturals, by writing out all programs of type ` ⇒ ` in
lexical order. Write `fᵢ` for the `i`'th function in this list.
Say we add a typing rule that applies the above enumeration
to interpret a natural as a function from naturals to naturals.
Γ ⊢ L ⦂ `
Γ ⊢ M ⦂ `
-------------- ⊢ℕ⇒ℕ
Γ ⊢ L · M ⦂ `
And that we add the corresponding reduction rule.
fᵢ(m) → n
--------- δ-ℕ⇒ℕ
i · m → n
Which of the following properties remain true in
the presence of this rule? For each one, write either
"remains true" or else "becomes false." If a property becomes
false, give a counterexample.
@ -1320,72 +1348,3 @@ false, give a counterexample.
- Preservation
#### Exercise: 2 stars, optional (stlc_variation5)
Suppose instead that we add the following new rule to the typing
relation:
Γ ⊢ L ⦂ ` ⇒ ` ⇒ `
Γ ⊢ M ⦂ `
------------------------------ (FunnyApp)
Γ ⊢ L · M ⦂ `
Which of the following properties of the STLC remain true in
the presence of this rule? For each one, write either
"remains true" or else "becomes false." If a property becomes
false, give a counterexample.
- Determinism of `step`
- Progress
- Preservation
#### Exercise: 2 stars, optional (stlc_variation6)
Suppose instead that we add the following new rule to the typing
relation:
Γ ⊢ L ⦂ `
Γ ⊢ M ⦂ `
--------------------- (FunnyApp')
Γ ⊢ L · M ⦂ `
Which of the following properties of the STLC remain true in
the presence of this rule? For each one, write either
"remains true" or else "becomes false." If a property becomes
false, give a counterexample.
- Determinism of `step`
- Progress
- Preservation
#### Exercise : 2 stars, optional (stlc_variation7)
Suppose we add the following new rule to the typing relation
of the STLC:
-------------------- (T_FunnyAbs)
∅ ⊢ ƛ x ⇒ N ⦂ `
Which of the following properties of the STLC remain true in
the presence of this rule? For each one, write either
"remains true" or else "becomes false." If a property becomes
false, give a counterexample.
- Determinism of `step`
- Progress
- Preservation