136 lines
4.1 KiB
Markdown
136 lines
4.1 KiB
Markdown
**Exercise 13.3.1**: I don't think you could model automatic garbage collection using single step semantics, given that it has no information about the outer evaluation context and whether a label will be used or not. We could write single step evaluation with an explicit context like this:
|
|
|
|
```
|
|
E ⩴ _ | t E | E v | !E | E := t | v := E | ref E
|
|
|
|
t | μ → t' | μ'
|
|
---------------------
|
|
E[t] | μ → E[t'] | μ'
|
|
```
|
|
|
|
and analyse for labels in `E`, but I think it would be cleaner to instead have an explicit freeing operator and error value:
|
|
|
|
```
|
|
t ⩴ ... | free t | error
|
|
|
|
┌───────────────┐
|
|
│ t | μ → t | μ │
|
|
└───────────────┘
|
|
|
|
t | μ → t' | μ'
|
|
-------------------------
|
|
free t | μ → free t' | μ'
|
|
|
|
--------------------------------
|
|
free l | μ → unit | μ[l ↦ error]
|
|
|
|
-----------------------
|
|
error t | μ → error | μ
|
|
|
|
-----------------------
|
|
v error | μ → error | μ
|
|
|
|
-------------------------
|
|
ref error | μ → error | μ
|
|
|
|
----------------------
|
|
!error | μ → error | μ
|
|
|
|
--------------------------
|
|
error := t | μ → error | μ
|
|
|
|
--------------------------
|
|
v := error | μ → error | μ
|
|
|
|
┌───────────────┐
|
|
│ Γ | Σ ⊢ t : T │
|
|
└───────────────┘
|
|
|
|
Γ | Σ ⊢ t : Ref T
|
|
---------------------
|
|
Γ | Σ ⊢ free t : Unit
|
|
|
|
-----------------
|
|
Γ | Σ ⊢ error : T
|
|
```
|
|
|
|
`free`ing updates the store with an `error` value , so the store still never shrinks. `error`s propagate upward, so if it's encountered anywhere inside a computation, the entire computation `error`s. The preservation theorem remains the same, but the progress theorem now says that either a well typed term evaluates to a value or it evaluates to `error` (if you don't consider `error` to be a value).
|
|
|
|
Unfortunately, the type system isn't strong enough to rule out usage after free (i.e. if a term is well typed then it never errors), and I'm not sure whether it would be possible to design a type system that does. Originally, I was thinking you could remove locations from the store typing, but then it's unclear which location should be removed when typing `free`, and even more unclear how to fix the preservation theorem.
|
|
|
|
_Theorem_ (preservation): If `Γ | Σ ⊢ μ`, `Γ | Σ ⊢ t : T`, `t | μ → t' | μ'`, then there exists `Σ'` such that `Γ | Σ' ⊢ μ'`, `Γ | Σ' ⊢ t' : T`, and `Σ ??? Σ'`.
|
|
|
|
We would want to allow, for instance, `t₁ := free (ref t₂)` where `t₁ ≠ t₂`, but not `t₁ := free t₁`, nor `(free t₁; t₁) := t₂`. All of these would shrink the store typing in some way, but it doesn't seem like there would be a way to combine the store typings from the two premises of typing assignment in a way that rules out the last two but not the first.
|
|
|
|
----
|
|
|
|
**Exercise 13.5.8**: First, suppose we had a sequencing operation `t₁; t₂`, which could be primitive, or just sugar for `(λ_. t₂) t₁` in our CBV language. Assuming the typing rules for the booleans and natural numbers from Chapter 8, as well as a `mult`iplication function, here is a factorial function:
|
|
|
|
```
|
|
(λn: Nat.
|
|
(λf: Ref (Nat → Nat).
|
|
λg: Ref (Nat → Nat).
|
|
f := λx: Nat.
|
|
if (iszero x)
|
|
then (succ 0)
|
|
else (mult x (!g (pred x)));
|
|
g := !f;
|
|
!g n)
|
|
(ref (λx: Nat. x))
|
|
(ref (λx: Nat. x)))
|
|
```
|
|
|
|
Given some concrete `n`, after evaluating the two initial references, this steps to the following:
|
|
|
|
```
|
|
lf ↦ λx: Nat. x
|
|
lg ↦ λx: Nat. x
|
|
|
|
lf := λx: Nat.
|
|
if (iszero x)
|
|
then (succ 0)
|
|
else (mult x (!lg (pred x)));
|
|
lg := !lf;
|
|
!lg n
|
|
```
|
|
|
|
After one step, we update `lf`:
|
|
|
|
```
|
|
lf ↦ λx: Nat.
|
|
if (iszero x)
|
|
then (succ 0)
|
|
else (mult x (!lg (pred x)))
|
|
lg ↦ λx: Nat. x
|
|
|
|
lg := !lf;
|
|
!lg n
|
|
```
|
|
|
|
After another step, we update `lg`:
|
|
|
|
```
|
|
lf ↦ λx: Nat.
|
|
if (iszero x)
|
|
then (succ 0)
|
|
else (mult x (!lg (pred x)))
|
|
lg ↦ λx: Nat.
|
|
if (iszero x)
|
|
then (succ 0)
|
|
else (mult x (!lg (pred x)))
|
|
|
|
!lg n
|
|
```
|
|
|
|
Then finally yield the factorial function we expect (dropping `lf` now that we no longer need it):
|
|
|
|
```
|
|
lg ↦ λx: Nat.
|
|
if (iszero x)
|
|
then (succ 0)
|
|
else (mult x (!lg (pred x)))
|
|
|
|
if (iszero n)
|
|
then (succ 0)
|
|
else (mult n (!lg (pred n)))
|
|
``` |