**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))) ```