CIS6700-Spring2025/Homework 4.md

4.1 KiB

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

freeing updates the store with an error value , so the store still never shrinks. errors propagate upward, so if it's encountered anywhere inside a computation, the entire computation errors. 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 multiplication 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)))