Exercise 16.1.
With the added field, the comparison required by S-Self contains 𝑋→𝑋<:𝑌→𝑌under 𝑋<:𝑌. Arrow subtyping asks for the domain premise (𝑌 <:𝑋) and the codomain premise (𝑋 <:𝑌). Only the latter is available. Thus the binary method is not covariant in the changing receiver type. If both interfaces instead use the fixed argument type, the comparison is 𝖯𝗈𝗂𝗇𝗍→𝑋<:𝖯𝗈𝗂𝗇𝗍→𝑌. Its premises are (𝖯𝗈𝗂𝗇𝗍 <:𝖯𝗈𝗂𝗇𝗍), by reflexivity, and (𝑋 <:𝑌), by the recursive assumption. Hence the fixed-argument method is compatible with the Self-subtyping proof.
Exercise 16.2.
The classifications, together with the comparisons induced by (𝐶 <:𝐷), are as follows. 𝐵(𝑋)polarity𝑋positive𝖭𝖺𝗍→𝑋positive𝑋→𝖡𝗈𝗈𝗅negative(𝑋→𝖡𝗈𝗈𝗅)→𝖭𝖺𝗍positive{𝑎:𝑋,𝑏:𝖭𝖺𝗍→𝑋}positive. The positive cases induce 𝐶<:𝐷,𝖭𝖺𝗍→𝐶<:𝖭𝖺𝗍→𝐷,(𝐶→𝖡𝗈𝗈𝗅)→𝖭𝖺𝗍<:(𝐷→𝖡𝗈𝗈𝗅)→𝖭𝖺𝗍,{𝑎:𝐶,𝑏:𝖭𝖺𝗍→𝐶}<:{𝑎:𝐷,𝑏:𝖭𝖺𝗍→𝐷}. The negative case instead induces 𝐷 →𝖡𝗈𝗈𝗅 <:𝐶 →𝖡𝗈𝗈𝗅. The fourth line has two variance reversals: (𝐶 <:𝐷) first gives (𝐷 →𝖡𝗈𝗈𝗅 <:𝐶 →𝖡𝗈𝗈𝗅); this is exactly the contravariant domain premise for the displayed outer-arrow comparison. The rejected positive use is (𝑋 →𝖡𝗈𝗈𝗅). To derive (𝐶 →𝖡𝗈𝗈𝗅 <:𝐷 →𝖡𝗈𝗈𝗅), arrow subtyping would require (𝐷 <:𝐶), the unavailable orientation. None of these five families is both positive and negative: each contains a genuine occurrence of (𝑋), and the occurrence paths all have one fixed parity.
Exercise 16.3.
Let 𝑟𝐶={𝑥=0,color=𝗍𝗋𝗎𝖾,clone=𝜆𝑢:𝖴𝗇𝗂𝗍.𝑐0,move=𝜆𝑑:𝖭𝖺𝗍.𝑐0}. Unfolding (𝑐0) in the receiver position and expanding derived selection gives (𝑐0⋅move)3⟼(𝗎𝗌𝖾𝖲𝖾𝗅𝖿(𝗉𝖺𝖼𝗄𝖲𝖾𝗅𝖿 𝐶 𝗐𝗂𝗍𝗁 𝑟𝐶 𝖺𝗌 𝐶)𝖺𝗌 𝑋<:𝐶,𝑧:𝖢𝗈𝗅𝗈𝗋𝖯𝗈𝗂𝗇𝗍𝖥(𝑋) 𝗂𝗇 𝑧.move)3. The use body has type (𝖭𝖺𝗍 →𝐶): projection first gives (𝑧.move :𝖭𝖺𝗍 →𝑋), and (𝑋 <:𝐶) gives (𝖭𝖺𝗍 →𝑋 <:𝖭𝖺𝗍 →𝐶). At the root, first perform the type substitution, (𝑧.move)[𝐶/𝑋]=𝑧.move,𝑧:𝖢𝗈𝗅𝗈𝗋𝖯𝗈𝗂𝗇𝗍𝖥(𝐶), and only then the term substitution, (𝑧.move)[𝑟𝐶/𝑧]=𝑟𝐶.move. Consequently (𝗎𝗌𝖾𝖲𝖾𝗅𝖿⋯𝗂𝗇 𝑧.move)3: 𝐶⟼(𝑟𝐶.move)3: 𝐶⟼(𝜆𝑑:𝖭𝖺𝗍.𝑐0)3: 𝐶⟼𝑐0: 𝐶. Before application, each function in the trace has type (𝖭𝖺𝗍 →𝐶), and (3 :𝖭𝖺𝗍); hence every displayed application has result type (𝐶). One further call-by-value step would unfold (𝑐0) to its package value, but the requested named endpoint is (𝑐0).
Exercise 16.4.
Write 𝑆𝑖=𝖲𝖾𝗅𝖿𝑋.𝑅𝑖(𝑋)(𝑖=0,1),𝑆=𝖲𝖾𝗅𝖿𝑋.𝑅(𝑋). Typing inversion for the redex supplies 𝐶<:𝑆0,𝑣:𝑅0(𝐶),𝑋<:𝑆,𝑥:𝑅(𝑋)⊢𝑏:𝐷,𝑋∉𝖥𝖵(𝐷). The first application of transitivity combines (𝐶 <:𝑆0) and (𝑆0 <:𝑆1), giving (𝐶 <:𝑆1). The second combines this judgment with (𝑆1 <:𝑆), giving (𝐶 <:𝑆). Separately, transitivity gives (𝑆0 <:𝑆); Self-subtyping inversion then yields 𝑋<:𝖳𝗈𝗉⊢𝑅0(𝑋)<:𝑅(𝑋). Type substitution with the well-formed hidden witness 𝐶 gives 𝑅0(𝐶) <:𝑅(𝐶). Payload subsumption therefore changes 𝑣 :𝑅0(𝐶) into 𝑣 :𝑅(𝐶).
Use the derived (𝐶 <:𝑆) in the bound-variable case of type substitution on the body premise. Since (𝑋) does not escape (𝐷), this gives 𝑥:𝑅(𝐶)⊢𝑏[𝐶/𝑋]:𝐷. Term substitution with (𝑣 :𝑅(𝐶)) finally gives ⊢𝑏[𝐶/𝑋][𝑣/𝑥]:𝐷, which is exactly the (UseSelf) reduct at the original result type. Replacing (𝐶) by (𝑆) would instead produce (𝑏[𝑆/𝑋]) and require a payload of type (𝑅(𝑆)). The runtime package contains (𝑣 :𝑅0(𝐶)), and neither packaging nor subsumption changes its hidden representation witness; there is no equality (𝐶 =𝑆). Such a replacement would erase the very abstraction that the package records.
Exercise 16.5.
Put (𝑄 ={𝑜𝑘 :𝖡𝗈𝗈𝗅}) and replace the two equality fields by (𝑋 →𝑄). Use payloads eq=𝜆𝑞:𝑃𝐸.{𝑜𝑘=𝖿𝖺𝗅𝗌𝖾}andeq=𝜆𝑞:𝐶𝐸.{𝑜𝑘=𝑞⋅color} for the plain and colored packages. If the forbidden selection coercion is inserted, the supposed term of type (𝑄) reduces as follows: 𝑟𝑃={𝑥=0,eq=𝜆𝑞:𝑃𝐸.{𝑜𝑘=𝖿𝖺𝗅𝗌𝖾}}. ((𝑐𝐸:𝑃𝐸)⋅eq)𝑝𝐸⟼∗(𝜆𝑞:𝐶𝐸.{𝑜𝑘=𝑞⋅color})𝑝𝐸⟼{𝑜𝑘=𝑝𝐸⋅color}⟼∗{𝑜𝑘=𝑟𝑃.color}. The last record is not a value, and its field term is neither a value nor a redex.
The missing judgment occurs when selection tries to turn the projected method 𝑋→𝑄into𝑃𝐸→𝑄(𝑋<:𝑃𝐸). Arrow subtyping would require (𝑃𝐸 <:𝑋), whereas the hidden bound gives only (𝑋 <:𝑃𝐸). The pointwise premise of S-Self compares the two record families at the same formal parameter (𝑋), so both equality fields there have the identical type (𝑋 →𝑄); record width can discard the color field. That premise says nothing about the distinct comparison (𝑋 →𝑄 <:𝑃𝐸 →𝑄) needed by selection, and therefore is not a term coercion.
Exercise 16.6.
The required client is 𝑟=Λ𝑋<:𝖱𝖾𝗌𝖾𝗍𝖥(𝑋).𝜆𝑝:𝑋.(𝑝.same)(𝑝.reset). Under (𝑋 <:𝖱𝖾𝗌𝖾𝗍𝖥(𝑋)), subsumption gives 𝑝:𝖱𝖾𝗌𝖾𝗍𝖥(𝑋)={𝑥:𝖭𝖺𝗍,reset:𝑋,same:𝑋→𝖡𝗈𝗈𝗅}. Projection therefore gives (𝑝.reset :𝑋) and (𝑝.same :𝑋 →𝖡𝗈𝗈𝗅); application gives the body type (𝖡𝗈𝗈𝗅). Abstraction and F-bound introduction yield 𝑟:∀𝑋<:𝖱𝖾𝗌𝖾𝗍𝖥(𝑋).𝑋→𝖡𝗈𝗈𝗅. The derivation chooses one (𝑋) and uses it for both receiver and argument. It never compares two different post-fixpoints, so it implies no subtype relation between them; in particular, the contravariant domain of (same) blocks the usual width-style recursive comparison.
Let (𝑅 =𝜇𝑋.𝖱𝖾𝗌𝖾𝗍𝖥(𝑋)) in the equi-recursive calculus. First, conversion is an equality judgment: 𝑅=𝖱𝖾𝗌𝖾𝗍𝖥(𝑅). Only afterward do reflexivity and conversion yield the subtyping premise needed for F-elimination: 𝑅<:𝖱𝖾𝗌𝖾𝗍𝖥(𝑅). Thus (𝑟[𝑅] :𝑅 →𝖡𝗈𝗈𝗅). The equality unfolds the recursive type; the subtype judgment discharges the bound. They are not one rule.
Exercise 16.7.
Define 𝖬𝖺𝗋𝗄𝖾𝖽𝖬𝗂𝗇𝖬𝖺𝗑𝖥(𝑋)={𝑛:𝖭𝖺𝗍,max:𝑋→𝑋,min:𝑋→𝑋,marked:𝖡𝗈𝗈𝗅},𝖬𝖺𝗋𝗄𝖾𝖽𝖬𝗂𝗇𝖬𝖺𝗑=𝜇𝑋.𝖬𝖺𝗋𝗄𝖾𝖽𝖬𝗂𝗇𝖬𝖺𝗑𝖥(𝑋),𝖬𝖺𝗋𝗄𝖾𝖽𝖬𝗂𝗇𝖬𝖺𝗑𝖮𝗉=𝜆𝑋:∗.𝖬𝖺𝗋𝗄𝖾𝖽𝖬𝗂𝗇𝖬𝖺𝗑𝖥(𝑋). For an arbitrary (𝑍 : ∗), record width, with reflexivity on every retained field, gives 𝖬𝖺𝗋𝗄𝖾𝖽𝖬𝗂𝗇𝖬𝖺𝗑𝖮𝗉(𝑍)<:𝖬𝗂𝗇𝖬𝖺𝗑𝖮𝗉(𝑍),𝖬𝗂𝗇𝖬𝖺𝗑𝖮𝗉(𝑍)<:𝖬𝖺𝗑𝖮𝗉(𝑍). The translation of 𝖬𝖺𝗋𝗄𝖾𝖽𝖬𝗂𝗇𝖬𝖺𝗑 is 𝜇𝖬𝖺𝗋𝗄𝖾𝖽𝖬𝗂𝗇𝖬𝖺𝗑𝖮𝗉. Rule S-OpPoint turns the pointwise judgments into operator comparisons, hence 𝖬𝖺𝗋𝗄𝖾𝖽𝖬𝗂𝗇𝖬𝖺𝗑#𝖬𝗂𝗇𝖬𝖺𝗑and𝖬𝗂𝗇𝖬𝖺𝗑#𝖬𝖺𝗑. Transitivity of operator subtyping gives (𝖬𝖺𝗋𝗄𝖾𝖽𝖬𝗂𝗇𝖬𝖺𝗑#𝖬𝖺𝗑) directly. Instantiating the client at the third operator gives, with 𝑀 =𝖬𝖺𝗋𝗄𝖾𝖽𝖬𝗂𝗇𝖬𝖺𝗑, preMax[𝑀]:𝑀→𝑀→𝑀. Thus both arguments and the result are exactly of type (𝖬𝖺𝗋𝗄𝖾𝖽𝖬𝗂𝗇𝖬𝖺𝗑). No argument or result is coerced to either (𝖬𝗂𝗇𝖬𝖺𝗑) or (𝖬𝖺𝗑).
Exercise 16.8.
The match-bound variable exposes the (𝑛)-field, so 𝑔=Λ𝑋#𝖬𝖺𝗑.𝜆𝑝:𝑋.𝑝.𝑛:∀𝑋#𝖬𝖺𝗑.𝑋→𝖭𝖺𝗍. Because 𝖬𝗂𝗇𝖬𝖺𝗑#𝖬𝖺𝗑, match application gives 𝑔[𝖬𝗂𝗇𝖬𝖺𝗑]:𝖬𝗂𝗇𝖬𝖺𝗑→𝖭𝖺𝗍.
In the target, write the bound operator as (Φ𝑋 ⪯𝖬𝖺𝗑𝖮𝗉). The translation is 𝑔†=ΛΦ𝑋⪯𝖬𝖺𝗑𝖮𝗉.𝜆𝑝:𝜇Φ𝑋.(𝗎𝗇𝖿𝗈𝗅𝖽Φ𝑋(𝑝)).𝑛. For (𝑝 :𝜇Φ𝑋), the derivation has the three requested steps: 𝗎𝗇𝖿𝗈𝗅𝖽Φ𝑋(𝑝):Φ𝑋(𝜇Φ𝑋),Φ𝑋(𝜇Φ𝑋)<:𝖬𝖺𝗑𝖮𝗉(𝜇Φ𝑋),𝗎𝗇𝖿𝗈𝗅𝖽Φ𝑋(𝑝):{𝑛:𝖭𝖺𝗍,max:𝜇Φ𝑋→𝜇Φ𝑋},(𝗎𝗇𝖿𝗈𝗅𝖽Φ𝑋(𝑝)).𝑛:𝖭𝖺𝗍. The second line is S-OpApp; the third is term subsumption; the fourth is projection. Instantiation substitutes (𝖬𝗂𝗇𝖬𝖺𝗑𝖮𝗉) for (Φ𝑋). Matching authorizes that operator instantiation, not a source subsumption rule. Thus an independently supplied (𝑚 :𝖬𝗂𝗇𝖬𝖺𝗑) may be passed to (𝑔[𝖬𝗂𝗇𝖬𝖺𝗑]), but the judgment (𝑚 :𝖬𝖺𝗑) is still not derivable.
Exercise 16.9.
Allocation starts the calculation: ⟨⋅,𝗋𝖾𝖿 0⟩⟼⟨{ℓ↦0},ℓ⟩. Take (Σ1 ={ℓ :𝖭𝖺𝗍}), replace (𝑟) by (ℓ) in (𝑘𝑟), and call the resulting value (𝑘ℓ). The invariant holds because the two domains are ({ℓ}) and ( ⋅;Σ1; ⋅ ⊢0 :𝖭𝖺𝗍). Writing (𝑎2 =𝑘ℓ), put 𝑟ℓ={contents=ℓ,set=𝜆𝑛:𝖭𝖺𝗍.(𝜆𝑤:𝖴𝗇𝗂𝗍.𝑘ℓ)(ℓ:=𝑛)},𝑝ℓ=𝗉𝖺𝖼𝗄𝖲𝖾𝗅𝖿 𝐾 𝗐𝗂𝗍𝗁 𝑟ℓ 𝖺𝗌 𝐾,𝑈𝑗(𝑎)=𝗎𝗌𝖾𝖲𝖾𝗅𝖿 𝑎 𝖺𝗌 𝑋<:𝐾,𝑧:𝑅𝐾(𝑋) 𝗂𝗇 𝑧.𝑗,𝐵2=𝜆𝑢:𝐾.!(𝑎2⋅contents). Here 𝑅𝐾 is the record family in 𝐾, and 𝑎 ⋅𝑗 expands to 𝑈𝑗(𝑎). Compatible-context and root steps give ⟨{ℓ↦0},𝐵2((𝑘ℓ⋅set)7)⟩=⟨{ℓ↦0},𝐵2(𝑈set(𝑘ℓ)7)⟩⟼⟨{ℓ↦0},𝐵2(𝑈set(𝑝ℓ)7)⟩⟼⟨{ℓ↦0},𝐵2((𝑟ℓ.set)7)⟩⟼⟨{ℓ↦0},𝐵2((𝜆𝑛:𝖭𝖺𝗍.(𝜆𝑤:𝖴𝗇𝗂𝗍.𝑘ℓ)(ℓ:=𝑛))7)⟩⟼⟨{ℓ↦0},𝐵2((𝜆𝑤:𝖴𝗇𝗂𝗍.𝑘ℓ)(ℓ:=7))⟩⟼⟨{ℓ↦7},𝐵2((𝜆𝑤:𝖴𝗇𝗂𝗍.𝑘ℓ)𝗎𝗇𝗂𝗍)⟩⟼⟨{ℓ↦7},𝐵2𝑘ℓ⟩⟼⟨{ℓ↦7},𝐵2𝑝ℓ⟩⟼⟨{ℓ↦7},!𝑈contents(𝑎2)⟩⟼⟨{ℓ↦7},!𝑈contents(𝑝ℓ)⟩⟼⟨{ℓ↦7},!(𝑟ℓ.contents)⟩⟼⟨{ℓ↦7},!ℓ⟩⟼⟨{ℓ↦7},7⟩. The only equality is expansion of derived selection. The subsequent arrows are, in order, fixpoint unfolding, (UseSelf), projection, beta, assignment, beta, fixpoint unfolding, beta, fixpoint unfolding, (UseSelf), projection, and dereference, all in the displayed left-to-right contexts. After assignment, the store and (Σ1) still have the same domain and (7 :𝖭𝖺𝗍), so the invariant is preserved. By contrast, (ℓ :=𝗍𝗋𝗎𝖾) would require (𝗍𝗋𝗎𝖾 :𝖭𝖺𝗍) in T-Assign; it is rejected before a configuration step exists.
Exercise 16.10.
Starting at each field type and multiplying the variance signs along the path to (𝑋) gives: fieldpolarity of 𝑋clone:𝑋+map:(𝖭𝖺𝗍→𝖡𝗈𝗈𝗅)→𝑋+equal:𝑋→𝖡𝗈𝗈𝗅−choose:(𝑋→𝖡𝗈𝗈𝗅)→𝑋+. The positive comparisons are 𝐶 <:𝐷 for clone, (𝖭𝖺𝗍→𝖡𝗈𝗈𝗅)→𝐶<:(𝖭𝖺𝗍→𝖡𝗈𝗈𝗅)→𝐷,(𝐶→𝖡𝗈𝗈𝗅)→𝐶<:(𝐷→𝖡𝗈𝗈𝗅)→𝐷 for map and choose, respectively. The negative field has 𝐷 →𝖡𝗈𝗈𝗅 <:𝐶 →𝖡𝗈𝗈𝗅. For (choose), the occurrence in the inner domain crosses two arrow domains and is positive; the result occurrence is directly positive. The largest legal positive subrecord therefore contains (clone), (map), and (choose), and removes only (equal). Keeping (equal) in a covariant record comparison would require (𝐷 <:𝐶) in order to derive (𝐶 →𝖡𝗈𝗈𝗅 <:𝐷 →𝖡𝗈𝗈𝗅); only (𝐶 <:𝐷) is available.
Exercise 16.11.
Let 𝑇=𝖲𝖾𝗅𝖿𝑋.{𝑛:𝖭𝖺𝗍,𝑏:𝖡𝗈𝗈𝗅,toggle:𝖴𝗇𝗂𝗍→𝑋},𝑡0=𝖿𝗂𝗑 𝑡:𝑇.𝗉𝖺𝖼𝗄𝖲𝖾𝗅𝖿 𝑇 𝗐𝗂𝗍𝗁{𝑛=0,𝑏=𝖿𝖺𝗅𝗌𝖾,toggle=𝜆𝑢:𝖴𝗇𝗂𝗍.𝑡} 𝖺𝗌 𝑇. The family is positive. Under (𝑡 :𝑇), the record has the payload type at witness (𝑇); reflexivity discharges (𝑇 <:𝑇), so T-PackSelf and T-Fix derive (𝑡0 :𝑇). If (𝑟𝑇) denotes this record with (𝑡0) in its last field, then (𝑡0⋅toggle)𝗎𝗇𝗂𝗍⟼∗(𝑟𝑇.toggle)𝗎𝗇𝗂𝗍⟼(𝜆𝑢:𝖴𝗇𝗂𝗍.𝑡0)𝗎𝗇𝗂𝗍⟼𝑡0.
Omit the natural field and put 𝑇′=𝖲𝖾𝗅𝖿𝑋.{𝑏:𝖡𝗈𝗈𝗅,toggle:𝖴𝗇𝗂𝗍→𝑋}. At an arbitrary formal (𝑋), record width gives the full payload family below the smaller one, so S-Self gives (𝑇 <:𝑇′). Opening the runtime package annotated (𝑇) at expected type (𝑇′), inversion yields hidden witness (𝐶 =𝑇), payload (𝑟𝑇 :𝑅𝑇(𝑇)), and (𝑇 <:𝑇′). Self-family inversion gives (𝑅𝑇(𝑋) <:𝑅𝑇′(𝑋)); type substitution gives (𝑅𝑇(𝑇) <:𝑅𝑇′(𝑇)); payload subsumption gives (𝑟𝑇 :𝑅𝑇′(𝑇)). Finally substitute (𝑇) for the hidden type binder and (𝑟𝑇) for the payload binder in the use body. This is the generalized (UseSelf) preservation calculation, with the omitted field discarded only by record subsumption.
Exercise 16.12.
Let 𝖮𝗋𝖽𝖮𝗉=𝜆𝑋:∗.𝖮𝗋𝖽𝖾𝗋𝖾𝖽(𝑋),𝖭𝖺𝗆𝖾𝖽𝖮𝗋𝖽𝖮𝗉=𝜆𝑋:∗.𝖭𝖺𝗆𝖾𝖽𝖮𝗋𝖽𝖾𝗋𝖾𝖽(𝑋). For every (𝑍 : ∗), record width gives (𝖭𝖺𝗆𝖾𝖽𝖮𝗋𝖽𝖾𝗋𝖾𝖽(𝑍) <:𝖮𝗋𝖽𝖾𝗋𝖾𝖽(𝑍)). Hence (𝖭𝖺𝗆𝖾𝖽𝖮𝗋𝖽𝖮𝗉 ⪯𝖮𝗋𝖽𝖮𝗉), so 𝜇𝖭𝖺𝗆𝖾𝖽𝖮𝗋𝖽𝖮𝗉#𝜇𝖮𝗋𝖽𝖮𝗉. Ordinary recursive subtyping need not hold. After unfolding, comparison of the (le) fields would compare (𝜇𝖭𝖺𝗆𝖾𝖽𝖮𝗋𝖽𝖮𝗉 →𝖡𝗈𝗈𝗅) with (𝜇𝖮𝗋𝖽𝖮𝗉 →𝖡𝗈𝗈𝗅); the arrow-domain premise has the reverse orientation and is not supplied by record width.
The source match-polymorphic client and its target are cmp=Λ𝑋#𝜇𝖮𝗋𝖽𝖮𝗉.𝜆𝑝:𝑋.𝜆𝑞:𝑋.(𝑝.le)𝑞,cmp†=ΛΦ⪯𝖮𝗋𝖽𝖮𝗉.𝜆𝑝:𝜇Φ.𝜆𝑞:𝜇Φ.((𝗎𝗇𝖿𝗈𝗅𝖽Φ𝑝).le)𝑞. For the target body, (𝗎𝗇𝖿𝗈𝗅𝖽Φ𝑝 :Φ(𝜇Φ)), (Φ(𝜇Φ) <:𝖮𝗋𝖽𝖮𝗉(𝜇Φ)), and subsumption exposes (le :𝜇Φ →𝖡𝗈𝗈𝗅); applying it to (𝑞 :𝜇Φ) gives (𝖡𝗈𝗈𝗅). Construction is explicit too. For example, if 𝑟𝑁={name=0,le=𝜆𝑞:𝜇𝖭𝖺𝗆𝖾𝖽𝖮𝗋𝖽𝖮𝗉.𝖿𝖺𝗅𝗌𝖾}, then (𝑟𝑁 :𝖭𝖺𝗆𝖾𝖽𝖮𝗋𝖽𝖮𝗉(𝜇𝖭𝖺𝗆𝖾𝖽𝖮𝗋𝖽𝖮𝗉)) and 𝑛 =𝖿𝗈𝗅𝖽𝖭𝖺𝗆𝖾𝖽𝖮𝗋𝖽𝖮𝗉(𝑟𝑁) :𝜇𝖭𝖺𝗆𝖾𝖽𝖮𝗋𝖽𝖮𝗉. Instantiating (cmp†) at (𝖭𝖺𝗆𝖾𝖽𝖮𝗋𝖽𝖮𝗉) and applying it to (𝑛,𝑛) unfolds (𝑛), exposes the record, projects (le), and beta-reduces to (𝖿𝖺𝗅𝗌𝖾).
The F-bounded analogue is Λ𝑋<:𝖮𝗋𝖽𝖾𝗋𝖾𝖽(𝑋).𝜆𝑝:𝑋.𝜆𝑞:𝑋.(𝑝.le)𝑞:∀𝑋<:𝖮𝗋𝖽𝖾𝗋𝖾𝖽(𝑋).𝑋→𝑋→𝖡𝗈𝗈𝗅. It may be instantiated at (𝑁 =𝜇𝑋.𝖭𝖺𝗆𝖾𝖽𝖮𝗋𝖽𝖾𝗋𝖾𝖽(𝑋)), because equi-recursive conversion and record width give (𝑁 <:𝖮𝗋𝖽𝖾𝗋𝖾𝖽(𝑁)). Neither construction derives the absent subsumption judgment (𝑚 :𝜇𝖮𝗋𝖽𝖮𝗉) from (𝑚 :𝜇𝖭𝖺𝗆𝖾𝖽𝖮𝗋𝖽𝖮𝗉): matching discharges a polymorphic bound; it does not coerce independently supplied values.
Exercise 16.13.
For preservation, induct on the reduction derivation. In each compatible context, invert the outer typing rule, apply the induction hypothesis to the unique active subterm, and rebuild that same rule; for record fields this is done at the leftmost nonvalue component. Beta and fixpoint unfolding use term substitution. The (𝗌𝗎𝖼𝖼), conditional, and record projection roots follow from inversion of their typing derivations.
For the Self root, canonical forms and typing inversion write the redex as a package with hidden witness 𝐶, runtime annotation 𝑆0 =𝖲𝖾𝗅𝖿 𝑋.𝑅0(𝑋), payload 𝑣 :𝑅0(𝐶), and expected type 𝑆 =𝖲𝖾𝗅𝖿 𝑋.𝑅(𝑋), with 𝐶<:𝑆0<:𝑆,𝑋<:𝑆,𝑥:𝑅(𝑋)⊢𝑏:𝐷,𝑋∉𝖥𝖵(𝐷). Self-subtyping inversion gives (𝑅0(𝑋) <:𝑅(𝑋)) under (𝑋 <:𝖳𝗈𝗉). Substitution of (𝐶) gives (𝑅0(𝐶) <:𝑅(𝐶)), and payload subsumption gives (𝑣 :𝑅(𝐶)). Transitivity gives (𝐶 <:𝑆), so hidden-witness type substitution in the body yields (𝑥 :𝑅(𝐶) ⊢𝑏[𝐶/𝑋] :𝐷). Payload substitution then derives (𝑏[𝐶/𝑋][𝑣/𝑥] :𝐷), exactly the reduct. This covers the only root for which the public annotation and runtime annotation may differ.
For progress, induct on a closed typing derivation after stripping final subsumption. Constants, lambdas, record values, and packages are values. For (𝗌𝗎𝖼𝖼), conditionals, applications, and projections, the induction hypotheses step the leftmost active subterm; otherwise canonical forms supply respectively a numeral, Boolean, lambda, or record with the requested label, and the corresponding root fires. A record steps its leftmost nonvalue field. A fixpoint always unfolds. For packing, the payload either steps or the package is a value. For a Self use, the receiver either steps or the Self canonical form supplies (𝗉𝖺𝖼𝗄𝖲𝖾𝗅𝖿 𝐶 𝗐𝗂𝗍𝗁 𝑣 𝖺𝗌 𝑆0), so the generalized (UseSelf) root fires even when (𝑆0 <:𝑆). These cases exhaust the grammar. Iterating preservation and applying progress at the last term proves that no closed well-typed term reaches a stuck term.
Exercise 16.14.
Extend the type to 𝐾+=𝖲𝖾𝗅𝖿𝑋.{contents:𝖱𝖾𝖿𝖭𝖺𝗍,set:𝖭𝖺𝗍→𝑋,bump:𝖴𝗇𝗂𝗍→𝑋}. After allocating (𝑟 :𝖱𝖾𝖿 𝖭𝖺𝗍), define 𝑟+𝑘={contents=𝑟,set=𝜆𝑛:𝖭𝖺𝗍.(𝜆𝑤:𝖴𝗇𝗂𝗍.𝑘)(𝑟:=𝑛),bump=𝜆𝑢:𝖴𝗇𝗂𝗍.(𝜆𝑤:𝖴𝗇𝗂𝗍.𝑘)(𝑟:=𝗌𝗎𝖼𝖼(!𝑟))},𝑘+𝑟=𝖿𝗂𝗑 𝑘:𝐾+.𝗉𝖺𝖼𝗄𝖲𝖾𝗅𝖿 𝐾+ 𝗐𝗂𝗍𝗁 𝑟+𝑘 𝖺𝗌 𝐾+. The annotations make the two sequencing lambdas explicit. From (𝑟 :𝖱𝖾𝖿 𝖭𝖺𝗍) one gets (!𝑟 :𝖭𝖺𝗍), then (𝗌𝗎𝖼𝖼(!𝑟) :𝖭𝖺𝗍), then (𝑟 :=𝗌𝗎𝖼𝖼(!𝑟) :𝖴𝗇𝗂𝗍); the inner application therefore returns (𝑘 :𝐾+). Thus (bump :𝖴𝗇𝗂𝗍 →𝐾+), the payload has the family instantiated at (𝐾+), and T-PackSelf plus T-Fix types (𝑘+𝑟 :𝐾+).
Allocation gives ⟨⋅,𝗋𝖾𝖿 0⟩⟼⟨𝜎0,ℓ⟩,Σ1={ℓ:𝖭𝖺𝗍}. Let (𝑎1 =𝑎2 =𝑘+ℓ), and put ̂𝑟ℓ={contents=ℓ,set=𝜆𝑛:𝖭𝖺𝗍.(𝜆𝑤:𝖴𝗇𝗂𝗍.𝑘+ℓ)(ℓ:=𝑛),bump=𝜆𝑢:𝖴𝗇𝗂𝗍.(𝜆𝑤:𝖴𝗇𝗂𝗍.𝑘+ℓ)(ℓ:=𝗌𝗎𝖼𝖼(!ℓ))},𝑝+ℓ=𝗉𝖺𝖼𝗄𝖲𝖾𝗅𝖿 𝐾+ 𝗐𝗂𝗍𝗁 ̂𝑟ℓ 𝖺𝗌 𝐾+,𝜎0={ℓ↦0},𝜎1={ℓ↦1},𝑈+𝑗(𝑎)=𝗎𝗌𝖾𝖲𝖾𝗅𝖿 𝑎 𝖺𝗌 𝑋<:𝐾+,𝑧:𝑅𝐾+(𝑋) 𝗂𝗇 𝑧.𝑗,𝐵+2=𝜆𝑧:𝐾+.!(𝑎2⋅contents),𝑒=𝐵+2(𝑈+bump(𝑎1)𝗎𝗇𝗂𝗍). Here 𝑅𝐾+ is the family displayed in 𝐾+, and 𝑎 ⋅𝑗 expands to 𝑈+𝑗(𝑎). The outer function has type (𝐾+ →𝖭𝖺𝗍); selection gives 𝑎1 ⋅bump :𝖴𝗇𝗂𝗍 →𝐾+, so (𝑒 :𝖭𝖺𝗍). The configuration trace is ⟨𝜎0,𝑒⟩⟼⟨𝜎0,𝐵+2(𝑈+bump(𝑝+ℓ)𝗎𝗇𝗂𝗍)⟩⟼⟨𝜎0,𝐵+2((̂𝑟ℓ.bump)𝗎𝗇𝗂𝗍)⟩⟼⟨𝜎0,𝐵+2((𝜆𝑢:𝖴𝗇𝗂𝗍.(𝜆𝑤:𝖴𝗇𝗂𝗍.𝑘+ℓ)(ℓ:=𝗌𝗎𝖼𝖼(!ℓ)))𝗎𝗇𝗂𝗍)⟩⟼⟨𝜎0,𝐵+2((𝜆𝑤:𝖴𝗇𝗂𝗍.𝑘+ℓ)(ℓ:=𝗌𝗎𝖼𝖼(!ℓ)))⟩⟼⟨𝜎0,𝐵+2((𝜆𝑤:𝖴𝗇𝗂𝗍.𝑘+ℓ)(ℓ:=𝗌𝗎𝖼𝖼(0)))⟩⟼⟨𝜎0,𝐵+2((𝜆𝑤:𝖴𝗇𝗂𝗍.𝑘+ℓ)(ℓ:=1))⟩⟼⟨𝜎1,𝐵+2((𝜆𝑤:𝖴𝗇𝗂𝗍.𝑘+ℓ)𝗎𝗇𝗂𝗍)⟩⟼⟨𝜎1,𝐵+2𝑘+ℓ⟩⟼⟨𝜎1,𝐵+2𝑝+ℓ⟩⟼⟨𝜎1,!𝑈+contents(𝑎2)⟩⟼⟨𝜎1,!𝑈+contents(𝑝+ℓ)⟩⟼⟨𝜎1,!(̂𝑟ℓ.contents)⟩⟼⟨𝜎1,!ℓ⟩⟼⟨𝜎1,1⟩. The intermediate types are determined at every root: unfolding 𝑘+ℓ yields 𝑝+ℓ :𝐾+; opening that package exposes ̂𝑟ℓ :𝑅𝐾+(𝐾+); projection yields ̂𝑟ℓ.bump :𝖴𝗇𝗂𝗍 →𝐾+; the two beta roots preserve result type 𝐾+; dereference, successor, and assignment have types 𝖭𝖺𝗍, 𝖭𝖺𝗍, and 𝖴𝗇𝗂𝗍; the sequencing beta returns 𝑘+ℓ :𝐾+. The second alias is unfolded and opened in the same way, after which contents projection has type 𝖱𝖾𝖿 𝖭𝖺𝗍 and the final dereference has type 𝖭𝖺𝗍. Before allocation the store typing and store are empty. After allocation, after assignment, and after dereference the store typing remains (Σ1); its unique cell contains respectively (0), (1), and (1), all of type (𝖭𝖺𝗍). The two aliases therefore share the same invariant cell.
If a field is replaced by (𝖱𝖾𝖿 𝑋), the occurrence of (𝑋) lies beneath an invariant reference. By the chapter’s polarity grammar it is neither positive nor negative, so Self formation fails. A hypothetical covariant comparison would require (𝖱𝖾𝖿 𝐶 <:𝖱𝖾𝖿 𝐷) from (𝐶 <:𝐷), but reference subtyping permits that judgment only when (𝐶 =𝐷); read/write covariance would be unsound.