exercise 15.1.
Twice applying T-Override to 𝑝0 :𝑃 gives 𝑝2 :𝑃. Put 𝑜2=[𝑥=𝜍(𝑠:𝑃)2,get=𝜍(𝑠:𝑃)𝑠.𝑥],𝑜3=[𝑥=𝜍(𝑠:𝑃)3,get=𝜍(𝑠:𝑃)𝑠.𝑥]. Compatible reduction first contracts the inner override and installs 2: 𝑝2⟼𝑜2.𝑥⇐𝜍(𝑠:𝑃)3⟼𝑜3. The outer override therefore installs 3, after which the two invocation roots give 𝑝2.get⟼∗𝑜3.get⟼𝑜3.𝑥⟼3. Separately 𝑝0.get ⟼𝑝0.𝑥 ⟼0. The unchanged old receiver still returning 0 after 𝑝2 is built is the exact functional, rather than imperative, observation.
exercise 15.2.
The receiver and replacement premises are 𝑝0 :𝑃 and 𝑠 :𝑃 ⊢𝑠.get :𝖭𝖺𝗍, the latter by T-Invoke. For the reduct, its new 𝑥-body has exactly that derivation. Its retained body is typed by the other invocation 𝑠 :𝑃 ⊢𝑠.𝑥 :𝖭𝖺𝗍. These are the two premises of T-Object, so the reduct has 𝑃, the type of the redex.
exercise 15.3.
Rule M-Object gives 𝑞 minimum type 𝑄; minimum invocation gives 𝑞.𝑥 :𝖭𝖺𝗍. Put 𝐴 =[𝑥 :𝖭𝖺𝗍]. Since 𝑄 <:𝐴, the receiver and constant-body premises of M-Override give the last term minimum type 𝐴. Declaratively, subsume 𝑞 :𝑄 to 𝑞 :𝐴, type 2 under 𝑠 :𝐴, and apply T-Override; this also yields 𝐴.
exercise 15.4.
Use the chapter’s types 𝑆 =[tag :𝖴𝗇𝗂𝗍] <:𝑇 =[], 𝑄 =[𝑚 :𝑆,𝑛 :𝑆], and 𝑃 =[𝑚 :𝑇,𝑛 :𝑆]. The proposed covariant rule gives 𝑄 <:𝑃, hence 𝑞 :𝑃. Rule T-Override types 𝑟 =𝑞.𝑚 ⇐𝜍(𝑠 :𝑃)𝑡0 :𝑃; invocation gives 𝑟.𝑛 :𝑆, and a second invocation gives ⋅ ⊢(𝑟.𝑛).tag :𝖴𝗇𝗂𝗍. The very first root, the override contraction, produces a runtime-𝑄 literal whose new 𝑚 body is 𝑡0 :𝑇, although T-Object requires 𝑆. That is the first missing preservation premise. Continuing makes the defect observable: 𝑟.𝑛 ⟼𝑟.𝑚 ⟼𝑡0, so tag selection is stuck.
For extraction, width is used exactly in 𝑎 :𝑄 <:𝑃, before T-Extract. It changes the claimed self parameter of the extracted method from 𝑄, which contains 𝑦, to 𝑃, which does not. Consequently the alleged 𝑃 →𝖭𝖺𝗍 function can be applied to 𝑝 :𝑃, but reduces to 𝗉𝗅𝗎𝗌(𝑝.𝑥,𝑝.𝑦) and is stuck at 𝑝.𝑦.
exercise 15.5.
Unfolding 𝖯𝗈𝗂𝗇𝗍 gives 𝖴𝖯𝗈𝗂𝗇𝗍, whose move component is 𝖯𝗈𝗂𝗇𝗍. Hence origin:𝖯𝗈𝗂𝗇𝗍,(𝗎𝗇𝖿𝗈𝗅𝖽origin).move:𝖯𝗈𝗂𝗇𝗍,𝑝2:𝖯𝗈𝗂𝗇𝗍 by two uses each of T-Unfold and T-Invoke. Let 𝑜0 be the runtime receiver inside origin. Abbreviate the retained move body by 𝑀(𝑠)=𝖿𝗈𝗅𝖽𝖯𝗈𝗂𝗇𝗍(𝑠.𝑥⇐𝜍(𝑡:𝖴𝖯𝗈𝗂𝗇𝗍)𝗌𝗎𝖼𝖼(𝑠.𝑥)). The two distinct updated literals are 𝑜1=[𝑥=𝜍(𝑡:𝖴𝖯𝗈𝗂𝗇𝗍)𝗌𝗎𝖼𝖼(𝑜0.𝑥),get=𝜍(𝑠:𝖴𝖯𝗈𝗂𝗇𝗍)𝑠.𝑥,move=𝜍(𝑠:𝖴𝖯𝗈𝗂𝗇𝗍)𝑀(𝑠)],𝑜2=[𝑥=𝜍(𝑡:𝖴𝖯𝗈𝗂𝗇𝗍)𝗌𝗎𝖼𝖼(𝑜1.𝑥),get=𝜍(𝑠:𝖴𝖯𝗈𝗂𝗇𝗍)𝑠.𝑥,move=𝜍(𝑠:𝖴𝖯𝗈𝗂𝗇𝗍)𝑀(𝑠)]. The first unfold and move invocation gives 𝖿𝗈𝗅𝖽𝖯𝗈𝗂𝗇𝗍𝑜1; unfolding that fold and invoking the retained move gives 𝖿𝗈𝗅𝖽𝖯𝗈𝗂𝗇𝗍𝑜2. Therefore (𝗎𝗇𝖿𝗈𝗅𝖽𝑝2).get⟼∗𝑜2.get⟼𝑜2.𝑥⟼𝗌𝗎𝖼𝖼(𝑜1.𝑥)⟼∗𝗌𝗎𝖼𝖼(𝗌𝗎𝖼𝖼(𝑜0.𝑥))⟼∗𝗌𝗎𝖼𝖼(𝗌𝗎𝖼𝖼(0))⟼2. The occurrences 𝑜0,𝑜1,𝑜2 make the two successive late-self substitutions visible.
exercise 15.6.
Write 𝑅(𝑓,ℎ) =𝑟𝐷𝑃(𝑓,ℎ). Then tr⋅(𝑝0) =𝑅(𝑓𝑥,𝑓get). In the translated override, the letrec root for 𝑟𝐷𝑃 and its parameter beta roots expose the folded package. The unfold root removes the fold; the generalized open root substitutes the actual witness and record; projection selects ℓ𝗎𝗉𝖽𝑥=𝜆𝑘:𝑃∗→𝖭𝖺𝗍.𝑅(𝑘,𝑓get). Its beta root yields 𝑅(𝑔,𝑓get), literally tr⋅(𝑝1).
Target congruence performs those roots inside the receiver of the translated get-invocation. A second letrec/beta unfolding, followed by unfold, open, and the two projections, gives 𝑓get(𝑅(𝑔,𝑓get)). Since 𝑓get =𝜆𝑠 :𝑃∗.tr𝑠:𝑃(𝑠.𝑥), beta gives the translated 𝑥-invocation on that same 𝑅-term. Its letrec/beta, unfold, open, selection, self, and beta roots give 𝑔(𝑅(𝑔,𝑓get))⟼1. No reverse step or frozen record identity is used.
exercise 15.7.
One unfold exposes equal 𝑥 and get components, but the shared move components are respectively 𝖯𝗈𝗂𝗇𝗍 and 𝖢𝗈𝗅𝗈𝗋𝖯𝗈𝗂𝗇𝗍. Invariance blocks both directions there (and width also blocks Point-to-ColorPoint). Changing the colored result to Point recovers the width judgment ColorPoint-to-Point, so point clients may invoke move, but the result has type Point and color cannot be invoked afterward.
exercise 15.8.
Under 𝑠 :𝑇, the three bodies have the judgments 0:𝖭𝖺𝗍,𝑠.𝑎:𝖭𝖺𝗍,𝑠.𝑏:𝖭𝖺𝗍. Thus T-Object gives 𝑡 :𝑇. Also 𝑠 :𝑇 ⊢4 :𝖭𝖺𝗍, so T-Override and then T-Invoke give (𝑡.𝑎⇐𝜍(𝑠:𝑇)4).𝑐:𝖭𝖺𝗍. The concrete updated receiver is 𝑡4=[𝑎=𝜍(𝑠:𝑇)4,𝑏=𝜍(𝑠:𝑇)𝑠.𝑎,𝑐=𝜍(𝑠:𝑇)𝑠.𝑏]. Compatible reduction first contracts the override in receiver position. Every remaining arrow is an invocation root whose displayed receiver is substituted for the method’s self binder: (𝑡.𝑎⇐𝜍(𝑠:𝑇)4).𝑐⟼𝑡4.𝑐⟼𝑡4.𝑏⟼𝑡4.𝑎⟼4. The two retained bodies therefore consult 𝑏 and then 𝑎 through 𝑡4, not through the original 𝑡.
exercise 15.9.
The three minimum types are 𝐵, 𝖴𝗇𝗂𝗍, and 𝐴. The last uses 𝐵 <:𝐴 in M-Override. The minimum-typing theorem says any declarative conclusion is a supertype of the corresponding result; explicitly these are object-width supertypes of 𝐵, only 𝖴𝗇𝗂𝗍 or Top for the projection, and object-width supertypes of 𝐴.
exercise 15.10.
From an arbitrary typing of 𝑣.ℓ𝑗, minimum typing gives the closed receiver a least object type 𝐴0 <:𝐴. Canonical forms makes 𝑣 a literal built at 𝐴0 =[ℓ𝑖 :𝐶𝑖]𝑖∈𝐼. Width invariance recovers 𝐶𝑗 =𝐵𝑗. Formation inversion gives 𝑠𝑗 :𝐴0 ⊢𝑏𝑗 :𝐶𝑗, and source substitution with 𝑣 :𝐴0 gives 𝑏𝑗[𝑣/𝑠𝑗] :𝐵𝑗. If the requested invocation conclusion arose by subsumption, restore that final supertype by T-Sub.
exercise 15.11.
Put 𝑄′ =[𝑚 :𝑆,𝑛 :𝑆,𝑘 :𝑆] and 𝑃′ =[𝑚 :𝑇,𝑛 :𝑆,𝑘 :𝑆]. Extend 𝑞 by 𝑘 =𝜍(𝑠 :𝑄′)𝑠.𝑛, and define 𝑟′ =𝑞′.𝑚 ⇐𝜍(𝑠 :𝑃′)𝑡0. Covariance claims 𝑄′ <:𝑃′, so 𝑟′ :𝑃′, 𝑟′.𝑘 :𝑆, and (𝑟′.𝑘).tag :𝖴𝗇𝗂𝗍. After the override root, let 𝑣 name the updated literal. The complete invocation schedule is (𝑟′.𝑘).tag⟼(𝑣.𝑘).tag⟼(𝑣.𝑛).tag⟼(𝑣.𝑚).tag⟼𝑡0.tag, which is stuck. The added 𝑘 →𝑛 call only delays the use of the illegally weakened 𝑚-result; the covariant 𝑆 <:𝑇 component remains the first failed premise.
exercise 15.12.
For 𝐴 =[ℓ :𝐵], 𝐶𝐴(𝑋) has ℓ𝗌𝖾𝗅 :𝑋 →𝐵∗, ℓ𝗎𝗉𝖽 :(𝑋 →𝐵∗) →𝑋, and 𝗌𝖾𝗅𝖿 :𝑋. At witness 𝑋 =𝐴∗, these become 𝐴∗ →𝐵∗, (𝐴∗ →𝐵∗) →𝐴∗, and 𝐴∗; there is no 𝐴∗/𝑋 mismatch. The record is packed at ∃𝑋 <:𝐴∗.𝐶𝐴(𝑋) and folded at 𝐴∗.
Put 𝑜′ =[ℓ =𝜍(𝑠 :𝐴)𝑐]. The source schedule is 𝑢⟼𝑜′,𝑢.ℓ⟼𝑜′.ℓ⟼𝑐[𝑜′/𝑠]. Let 𝑓𝑏 =𝜆𝑠 :𝐴∗.trΓ,𝑠:𝐴(𝑏), 𝑔𝑐 =𝜆𝑠 :𝐴∗.trΓ,𝑠:𝐴(𝑐), and 𝑅(𝑓) =𝑟𝐷𝐴(𝑓). The letrec/beta, unfold, open, update projection, and application beta roots give trΓ(𝑢)⟼∗𝑅(𝑔𝑐)=trΓ(𝑜′). Target congruence therefore gives trΓ(𝑢.ℓ) ⟼∗trΓ(𝑜′.ℓ). The next letrec/beta unfolding, unfold, open, selection and self projections, and application beta roots give 𝑔𝑐(𝑅(𝑔𝑐))⟼trΓ,𝑠:𝐴(𝑐)[trΓ(𝑜′)/𝑠]=𝛼trΓ(𝑐[𝑜′/𝑠]) by translation substitution. This is the translation of each source reduct, not the incorrect term 𝑐[𝑢/𝑠].
exercise 15.13.
For the ordinary object use the chapter’s 𝑜0 :𝖴𝖯𝗈𝗂𝗇𝗍, origin =𝖿𝗈𝗅𝖽𝖯𝗈𝗂𝗇𝗍𝑜0, and next =(𝗎𝗇𝖿𝗈𝗅𝖽 origin).move. The object premise types 𝑥,get at 𝖭𝖺𝗍; its move body overrides 𝑥 in 𝖴𝖯𝗈𝗂𝗇𝗍 and folds the result, so it has 𝖯𝗈𝗂𝗇𝗍. Hence origin and next both have 𝖯𝗈𝗂𝗇𝗍.
Put 𝖴𝖢𝗈𝗅𝗈𝗋𝖯𝗈𝗂𝗇𝗍=[𝑥:𝖭𝖺𝗍,get:𝖭𝖺𝗍,move:𝖢𝗈𝗅𝗈𝗋𝖯𝗈𝗂𝗇𝗍,color:𝖭𝖺𝗍],𝑁(𝑠)=𝖿𝗈𝗅𝖽𝖢𝗈𝗅𝗈𝗋𝖯𝗈𝗂𝗇𝗍(𝑠.𝑥⇐𝜍(𝑡:𝖴𝖢𝗈𝗅𝗈𝗋𝖯𝗈𝗂𝗇𝗍)𝗌𝗎𝖼𝖼(𝑠.𝑥)),𝑐0=[𝑥=𝜍(𝑠:𝖴𝖢𝗈𝗅𝗈𝗋𝖯𝗈𝗂𝗇𝗍)0,get=𝜍(𝑠:𝖴𝖢𝗈𝗅𝗈𝗋𝖯𝗈𝗂𝗇𝗍)𝑠.𝑥,move=𝜍(𝑠:𝖴𝖢𝗈𝗅𝗈𝗋𝖯𝗈𝗂𝗇𝗍)𝑁(𝑠),color=𝜍(𝑠:𝖴𝖢𝗈𝗅𝗈𝗋𝖯𝗈𝗂𝗇𝗍)7]. Invocation gives 𝑠.𝑥 :𝖭𝖺𝗍. Override types the payload of 𝑁 at 𝖴𝖢𝗈𝗅𝗈𝗋𝖯𝗈𝗂𝗇𝗍, and fold gives 𝖢𝗈𝗅𝗈𝗋𝖯𝗈𝗂𝗇𝗍. The other bodies have their displayed ground types. Thus corigin=𝖿𝗈𝗅𝖽𝖢𝗈𝗅𝗈𝗋𝖯𝗈𝗂𝗇𝗍𝑐0,cnext=(𝗎𝗇𝖿𝗈𝗅𝖽corigin).move:𝖢𝗈𝗅𝗈𝗋𝖯𝗈𝗂𝗇𝗍. After one type unfold, width comparison reaches the shared move fields 𝖢𝗈𝗅𝗈𝗋𝖯𝗈𝗂𝗇𝗍 and 𝖯𝗈𝗂𝗇𝗍. Invariance rejects them, although each calculus derivation is independently safe.
exercise 15.14.
Write 𝑖:=[ℓ=𝜍(𝑡)[]],𝑎:=[ℓ=𝜍(𝑠)𝑖]. The empty literal has [] :[]. Choosing 𝐴 =[ℓ :[]] as the self type for the inner one-method literal gives the explicit formation 𝑡:𝐴⊢[]:[]⋅⊢𝑖:𝐴T−Object. Width gives 𝐴 <:[], so weakening and the explicit subsumption 𝑠:𝐴⊢𝑖:𝐴𝐴<:[]𝑠:𝐴⊢𝑖:[]T−Sub let outer object formation conclude 𝑎 :𝐴. For the second typing, weaken the same inner formation to 𝑠 :𝐴′ ⊢𝑖 :𝐴, where 𝐴′ =[ℓ :𝐴], and use it directly as the outer body premise; outer formation concludes 𝑎 :𝐴′.
If some 𝐶 were below both 𝐴 and 𝐴′, width-invariant subtyping would require the ℓ-component of 𝐶 to equal both [] and 𝐴. These distinct types cannot both be that component. Erasing the self annotation therefore removes the syntax that fixed the conclusions of object formation and override, precisely the two annotated cases used by the minimum-type uniqueness proof.
exercise 15.15.
Here is the incorrect target fragment explicitly. Put 𝑅:=𝜇𝑌.{𝑥𝗌𝖾𝗅:𝑌→𝖭𝖺𝗍,get𝗌𝖾𝗅:𝑌→𝖭𝖺𝗍,𝗌𝖾𝗅𝖿:𝑌}, and define 𝑓𝑥=𝜆𝑠:𝑅.0,𝑔=𝜆𝑠:𝑅.1,𝑓get=𝜆𝑠:𝑅.(𝗎𝗇𝖿𝗈𝗅𝖽𝑠).𝑥𝗌𝖾𝗅((𝗎𝗇𝖿𝗈𝗅𝖽𝑠).𝗌𝖾𝗅𝖿). Let the deliberately bad recursive declaration and its old receiver be 𝐷−≡make(𝑢:𝖴𝗇𝗂𝗍):𝑅=𝖿𝗈𝗅𝖽𝑅{𝑥𝗌𝖾𝗅=𝑓𝑥,get𝗌𝖾𝗅=𝑓get,𝗌𝖾𝗅𝖿=make(𝗎𝗇𝗂𝗍)},𝑟0:=𝑟𝐷−(𝗎𝗇𝗂𝗍). The letrec and beta roots expose the old record: 𝑟0⟼∗𝖿𝗈𝗅𝖽𝑅{𝑥𝗌𝖾𝗅=𝑓𝑥,get𝗌𝖾𝗅=𝑓get,𝗌𝖾𝗅𝖿=𝑟0}. Functional record update of only the selection field is the target term 𝑟−1:=𝖿𝗈𝗅𝖽𝑅{𝑥𝗌𝖾𝗅=𝑔,get𝗌𝖾𝗅=(𝗎𝗇𝖿𝗈𝗅𝖽𝑟0).get𝗌𝖾𝗅,𝗌𝖾𝗅𝖿=(𝗎𝗇𝖿𝗈𝗅𝖽𝑟0).𝗌𝖾𝗅𝖿}. Thus the frozen translation of 𝑝1.get has the complete reduction (𝗎𝗇𝖿𝗈𝗅𝖽𝑟−1).get𝗌𝖾𝗅((𝗎𝗇𝖿𝗈𝗅𝖽𝑟−1).𝗌𝖾𝗅𝖿)⟼∗(𝗎𝗇𝖿𝗈𝗅𝖽𝑟0).get𝗌𝖾𝗅((𝗎𝗇𝖿𝗈𝗅𝖽𝑟0).𝗌𝖾𝗅𝖿)⟼∗𝑓get𝑟0⟼(𝗎𝗇𝖿𝗈𝗅𝖽𝑟0).𝑥𝗌𝖾𝗅((𝗎𝗇𝖿𝗈𝗅𝖽𝑟0).𝗌𝖾𝗅𝖿)⟼∗𝑓𝑥𝑟0⟼0. Beside it, the source uses the newly constructed receiver 𝑝′1 =[𝑥 =𝜍(𝑠 :𝑃)1,get =𝜍(𝑠 :𝑃)𝑠.𝑥]: 𝑝1.get⟼𝑝′1.get⟼𝑝′1.𝑥⟼1. The defective term is (𝗎𝗇𝖿𝗈𝗅𝖽 𝑟0).𝗌𝖾𝗅𝖿 =𝑟0, retained inside 𝑟−1. Recursive creation instead rebuilds the suite as 𝑟𝐷𝑃(𝑔,𝑓get) and ties its self field to that same updated application.
exercise 15.16.
Induct on 𝑏, freshening binders. In an object body both substitutions pass under each fresh self binder, and the induction hypothesis proves equality; in a fold payload they commute homomorphically and the type annotation obeys ordinary type-substitution composition. The variable cases are immediate, including 𝑏 =𝑠. No freshness condition on 𝑋 in 𝑎 is needed because the left side explicitly uses 𝑎[𝐶/𝑋]. Type terms contain no term variables, so 𝐶 cannot contain 𝑠.