exercise 35.1.
Let 𝐹𝐿 =𝗍𝗁𝗋𝗈𝗐 [ ] 𝗍𝗈 𝖼𝗈𝗇𝗍(𝐾0). The complete first invocation is 𝐿▹𝗍𝗁𝗋𝗈𝗐 5 𝗍𝗈𝖼𝗈𝗇𝗍(𝐾0)⟶𝐿;𝐹𝐿▹5⟶𝐿;𝐹𝐿◃5⟶𝐿;𝗍𝗁𝗋𝗈𝗐 5 𝗍𝗈 []▹𝖼𝗈𝗇𝗍(𝐾0)⟶𝐿;𝗍𝗁𝗋𝗈𝗐 5 𝗍𝗈 []◃𝖼𝗈𝗇𝗍(𝐾0)⟶𝐾0◃5⟶∙◃6. The last step uses 𝐾0 = ∙;𝖺𝖽𝖽1[ ]. Replacing 𝐿 by 𝐿′ changes only the first four states: 𝐿′▹𝗍𝗁𝗋𝗈𝗐 5 𝗍𝗈𝖼𝗈𝗇𝗍(𝐾0)⟶∗𝐾0◃5⟶∙◃6. In both runs the final throw transition pattern-matches the same value 𝖼𝗈𝗇𝗍(𝐾0), discards the current stack, and produces 𝐾0 ◃5. Its right-hand side contains 𝐾0, not a modified or consumed stack. That transition is the operational evidence that the continuation is persistent rather than one-shot.
exercise 35.2.
Fix the ambient answer 𝑅, suppose 𝐾 :𝐵 ⇒𝑅, and invert T-Throw to obtain ⊢𝑅𝑒1 :𝐴, ⊢𝑅𝑒2 :𝖢𝗈𝗇𝗍 𝐴, and the arbitrary local result 𝐵. For the push step, 𝐾:𝐵⇒𝑅𝗍𝗁𝗋𝗈𝗐 [] 𝗍𝗈 𝑒2:𝐴⇒𝐵𝐾;𝗍𝗁𝗋𝗈𝗐 [] 𝗍𝗈 𝑒2:𝐴⇒𝑅, so the reduct evaluating 𝑒1 :𝐴 is a state of result 𝑅.
For the first return, suppose ⊢𝑅𝑣 :𝐴. The old top frame accepts 𝐴 and produces 𝐵. The new top frame has 𝗍𝗁𝗋𝗈𝗐 𝑣 𝗍𝗈 []:𝖢𝗈𝗇𝗍𝐴⇒𝐵 by the value premise 𝑣 :𝐴; hence 𝐾;𝗍𝗁𝗋𝗈𝗐 𝑣 𝗍𝗈 [ ] accepts the type of 𝑒2 and still returns 𝑅.
For the final return, state typing gives 𝐾;𝗍𝗁𝗋𝗈𝗐 𝑣 𝗍𝗈 []:𝖢𝗈𝗇𝗍𝐴⇒𝑅,⊢𝑅𝑤:𝖢𝗈𝗇𝗍𝐴. Canonical continuations is used exactly here: 𝑤 =𝖼𝗈𝗇𝗍(𝐾′) with 𝐾′ :𝐴 ⇒𝑅. Since 𝑣 :𝐴, the reduct 𝐾′ ◃𝑣 has result type 𝑅. The discarded stack 𝐾 was allowed to produce the unrelated local type 𝐵; the ambient subscript forces the restored stack 𝐾′ to have the same final answer 𝑅.
exercise 35.3.
Write 𝑉 =𝐴𝗏. In the letcc clause the translated captured variable has type 𝑐 :𝑉 →𝟎. If 𝑒𝖼 :(𝑉 →𝟎) →𝟎, then 𝜆𝑘:𝑉→𝟎.(𝑒𝖼[𝑘/𝑐])𝑘:(𝑉→𝟎)→𝟎=𝐴𝖼. For throw, if 𝑒1 :𝐴, 𝑒2 :𝖢𝗈𝗇𝗍 𝐴, and the arbitrary source result is 𝐵, then 𝑎:𝑉,𝑐:𝑉→𝟎,𝑐𝑎:𝟎,𝜆𝑐.𝑐𝑎:(𝑉→𝟎)→𝟎. Thus 𝑒𝖼2(𝜆𝑐.𝑐 𝑎) :𝟎, 𝜆𝑎.𝑒𝖼2(𝜆𝑐.𝑐 𝑎) :𝑉 →𝟎, and 𝜆𝑘:𝐵𝗏→𝟎.𝑒𝖼1(𝜆𝑎.𝑒𝖼2(𝜆𝑐.𝑐𝑎)):𝐵𝖼. The binder 𝑘 is unused, matching the discarded throw site.
Here are all four machine roots; in particular this includes the three throw transitions. Capture has the marked beta step (𝗅𝖾𝗍𝖼𝖼 𝑐 𝗂𝗇 𝑒)𝖼𝐾𝗄ℎ⟶+𝛽𝑒𝖼[𝐾𝗄ℎ/𝑐]𝐾𝗄ℎ. The initial throw push is (𝗍𝗁𝗋𝗈𝗐 𝑒1 𝗍𝗈 𝑒2)𝖼𝐾𝗄ℎ⟶+𝛽𝑒𝖼1(𝜆𝑎.𝑒𝖼2(𝜆𝑐.𝑐𝑎)). Returning 𝑣 to the first throw frame contracts the displayed 𝑎: (𝜆𝑎.𝑒𝖼2(𝜆𝑐.𝑐𝑎))𝑣𝗏⟶+𝛽𝑒𝖼2(𝜆𝑐.𝑐𝑣𝗏). Finally, returning 𝖼𝗈𝗇𝗍(𝐾′) contracts 𝑐: (𝜆𝑐.𝑐𝑣𝗏)𝐾′ℎ𝗄⟶+𝛽𝐾′ℎ𝗄𝑣𝗏. Each source root therefore contributes at least one target beta step.
exercise 35.4.
Put 𝑉 =𝐴𝗏 and 𝑆 =𝑉 +(𝑉 →𝟎). Expanding the two letcc clauses, both injections, and throw, then contracting administrative beta redexes, gives 𝗅𝖾𝗆𝖼𝐴⟶∗𝛽𝜆ℎ:𝑆→𝟎.ℎ(𝗂𝗇𝗋(𝜆𝑎:𝑉.ℎ(𝗂𝗇𝗅𝑎))). Indeed 𝜆𝑎.ℎ(𝗂𝗇𝗅 𝑎) :𝑉 →𝟎, so the right injection has type 𝑆; its application to ℎ has type 𝟎, and abstraction gives (𝑆 →𝟎) →𝟎, the required type.
The outer occurrence ℎ(𝗂𝗇𝗋(𝜆𝑎.ℎ(𝗂𝗇𝗅 𝑎))) is the first call of the supplied continuation, with apparent evidence for the right summand. If a client invokes that evidence at 𝑎 :𝑉, the inner occurrence ℎ(𝗂𝗇𝗅 𝑎) calls the same continuation again with evidence for the left summand. The repeated occurrence of ℎ, rather than an equation between the two injections, is the CPS image of the change of mind.
exercise 35.5.
With Δ0 =(𝛾 ::𝖳), 𝜏 =𝛾, and 𝜌 =𝜄, the first effect clause of theorem 35.30 is 𝛼::𝖳.∀𝛾::𝖳.((𝛼𝜄→𝛾)𝜄→𝛾)⇒𝛼. For an operation result 𝛼, the parameter is one function which, for every chosen 𝛾, consumes a captured continuation 𝛼 →𝛾 and produces an answer 𝛾. Therefore ∀𝛾 must bind both the continuation codomain and the answer codomain. The ill-scoped alternative (∀𝛾.𝛼 →𝛾) →𝛾 leaves the final 𝛾 free; moving the quantifier only into the continuation type also allows its instantiation to disagree with the surrounding answer. Neither is the image of the well-kinded source effect.
exercise 35.6.
The four rows are: translation(delimiter reinstated, target recursive, closure)𝗌𝗁𝗂𝖿𝗍0𝖣𝖧←←←←←←→deep(yes, no,⟶+)deep𝖣𝖣←←←←←←→𝗌𝗁𝗂𝖿𝗍0(yes, no,⟶+𝑖)𝖼𝗈𝗇𝗍𝗋𝗈𝗅0𝖲𝖧⟶shallow(no, yes,⟶+)shallow𝖲𝖣⟶𝖼𝗈𝗇𝗍𝗋𝗈𝗅0(no, yes,⟶+) In the first row the handler resumption is 𝜆𝑧.𝗁𝖺𝗇𝖽𝗅𝖾 𝐸[𝑧]𝐷; in the second the translated operation passes 𝜆𝑥.𝑘 𝑥 ℎ, so the reset/return code is retained. The second root contracts 𝜆𝑤.𝑄[𝑤] beneath 𝜆𝑧, which is precisely why only that direction needs arbitrary-context ⟶𝑖.
In the shallow rows the captured resumption is 𝜆𝑧.𝐸[𝑧], with no handler, reset, or return clause. Its type may expose the same leading effect, so both target effects are defined by 𝜇𝛼. Both displayed shallow root calculations contract only in evaluation position and hence use ordinary ⟶+.
exercise 35.7.
Under 𝑘 :¬(∃𝑥 :𝖭𝖺𝗍.𝑥 =1), the leaves and pair are 1:𝖭𝖺𝗍,𝗋𝖾𝖿𝗅:1=1,(1,𝗋𝖾𝖿𝗅):∃𝑥:𝖭𝖺𝗍.𝑥=1. Rule Dep-Throw-P assigns 𝗍𝗁𝗋𝗈𝗐𝑘(1,𝗋𝖾𝖿𝗅) the arbitrary local result type 0 =1. Hence (0,𝗍𝗁𝗋𝗈𝗐𝑘(1,𝗋𝖾𝖿𝗅)):∃𝑥:𝖭𝖺𝗍.𝑥=1, and Dep-Callcc-P gives 𝑝0 :∃𝑥 :𝖭𝖺𝗍.𝑥 =1.
All three reductions, including the transformed throw, are 𝗐𝗂𝗍𝑝0⟼𝖼𝖺𝗅𝗅𝖼𝖼𝑘(𝗐𝗂𝗍(0,𝗍𝗁𝗋𝗈𝗐𝑘(𝗐𝗂𝗍(1,𝗋𝖾𝖿𝗅))))⟼𝖼𝖺𝗅𝗅𝖼𝖼𝑘0⟼0. The first step is commuting projection, the second is pair projection under number-level 𝖼𝖺𝗅𝗅𝖼𝖼, and the third is vacuity. Projection gives 𝗉𝗋𝖿 𝑝0 :𝗐𝗂𝗍 𝑝0 =1. Conversion along the displayed reduction gives 𝗋𝖾𝖿𝗅 :𝗐𝗂𝗍 𝑝0 =0. Taking 𝐵(𝑥) ≡𝑥 =0, Dep-Subst derives 𝗌𝗎𝖻𝗌𝗍(𝗉𝗋𝖿𝑝0)𝗋𝖾𝖿𝗅:𝐵(1),𝐵(1)≡(1=0). The absent 𝜆𝖪 rule is the call-by-name commuting rule which moves 𝗐𝗂𝗍([ ]) through a captured continuation (together with its compatibility closure beneath number-level 𝖼𝖺𝗅𝗅𝖼𝖼). The CBV stack machine has no dependent projection root of this form.
exercise 35.8.
For a fresh 𝑢, 𝜆𝑧.𝑧 :𝑢 →𝑢. Since the surrounding context is empty, ML-Let closes this type to 𝑖 :∀𝑢.𝑢 →𝑢. Instantiating the first occurrence at 𝗂𝗇𝗍 gives 𝑖 1 :𝗂𝗇𝗍; instantiating the second at 𝖻𝗈𝗈𝗅 gives 𝑖 𝗍𝗋𝗎𝖾 :𝖻𝗈𝗈𝗅. The sequencing abbreviation discards the first result, so the displayed term has type 𝖻𝗈𝗈𝗅. Its right-hand side is a lambda, hence it satisfies values-only let.
For the unrestricted continuation-plugging calculation, assume that 𝑥 has a monotype 𝜏. Closing the type of the bound expression 𝑥 relative to the context 𝑥 :𝜏 quantifies no variable: every variable free in 𝜏 is already free in the context. Thus 𝑓 also has monotype 𝜏. Typing 𝑓 1 forces its domain to be 𝗂𝗇𝗍, whereas typing 𝑓 𝗍𝗋𝗎𝖾 forces the same domain to be 𝖻𝗈𝗈𝗅. No monotype satisfies both constraints. With 𝑥 :∀𝑢.𝑢 →𝑢, the let can instantiate its right-hand side at a fresh 𝑢 →𝑢, close that type again, and let the two occurrences of 𝑓 instantiate 𝑢 separately. Thus 𝐾0[𝑥] is typable. The plugged expression is not a term of the values-only fragment, because its let right-hand side is a variable rather than a value; it is used only to test the unrestricted evaluator’s continuation invariant. This is precisely the gap between the monomorphic premise needed to reify the continuation and the polymorphic premise available to unrestricted let-generalization.
In 𝑃, the rejected node is the outer let whose right-hand side is 𝐸 =𝖼𝖺𝗅𝗅𝖼𝖼(𝜆𝑘.𝜆𝑥.𝗍𝗁𝗋𝗈𝗐 𝑘 (𝜆𝑦.𝑥)): 𝐸 is an application, not a syntactic value. Changing the body to 𝑓 1;𝑓 1 makes the saved continuation monomorphically typable at 𝗂𝗇𝗍 →𝗂𝗇𝗍, but it does not change that syntactic node. The selected values-only repair rejects it nonetheless; the theorem does not perform a finer safety analysis of individual nonvalues.
exercise 35.9.
Let 𝐾3 = ∙;𝖺𝖽𝖽3[ ]. Since 𝖺𝖽𝖽3[ ] :𝖭𝖺𝗍 ⇒𝖭𝖺𝗍, 𝐾3 :𝖭𝖺𝗍 ⇒𝖭𝖺𝗍. The top frame has [ ]7 :(𝖭𝖺𝗍 →𝖭𝖺𝗍) ⇒𝖭𝖺𝗍, so 𝐾=𝐾3;[]7:(𝖭𝖺𝗍→𝖭𝖺𝗍)⇒𝖭𝖺𝗍. Writing 𝖺𝖽𝖽𝗏3 =𝜆𝑛.𝜆𝑘.𝑘(3 +𝑛), the stack translation is (𝐾3)𝗄ℎ=𝜆𝑛.𝖺𝖽𝖽𝗏3𝑛ℎ:𝖭𝖺𝗍→𝟎,𝐾𝗄ℎ=𝜆𝑓.7𝖼(𝜆𝑎.𝑓𝑎(𝐾3)𝗄ℎ):(𝖭𝖺𝗍→𝖭𝖺𝗍𝖼)→𝟎. Here 𝑎 :𝖭𝖺𝗍, 𝑓 :𝖭𝖺𝗍 →(𝖭𝖺𝗍 →𝟎) →𝟎, and (𝐾3)𝗄ℎ :𝖭𝖺𝗍 →𝟎, so every application is typed.
For 𝑖 =𝜆𝑥.𝑥, the source run is 𝐾◃𝑖⟶𝐾3;𝑖[]▹7⟶𝐾3;𝑖[]◃7⟶𝐾3▹7⟶𝐾3◃7⟶∙◃10. On the target side the exact typed spine is 𝐾𝗄ℎ𝑖𝗏⟶𝛽7𝖼(𝜆𝑎.𝑖𝗏𝑎(𝐾3)𝗄ℎ)⟶+𝛽𝑖𝗏7(𝐾3)𝗄ℎ⟶+𝛽(𝐾3)𝗄ℎ7⟶∗𝛽𝛿ℎ10. The first reductions pass 7 to 𝑖𝗏, then pass its result to (𝐾3)𝗄ℎ, and finally compute 3 +7.
exercise 35.10.
The two branches of 𝐶 return 𝐴: the left branch returns 𝑥 :𝐴, and T-Throw gives the right branch arbitrary result 𝐴 from 𝑎 :𝐴 and 𝑞 :𝖢𝗈𝗇𝗍 𝐴. Thus 𝐶 :(𝐴 +𝖢𝗈𝗇𝗍 𝐴) ⇒𝐴, and 𝐾;𝐶 :(𝐴 +𝖢𝗈𝗇𝗍 𝐴) ⇒𝑅.
Put 𝐽 =𝐾;𝐶 and 𝐽′ =𝐽;𝗂𝗇𝗅[ ]. Splicing the two traces gives one run: 𝐽▹𝗅𝖾𝗆𝐴⟶∗𝐽◃𝗂𝗇𝗋(𝖼𝗈𝗇𝗍(𝐽′))⟶𝐾▹𝗍𝗁𝗋𝗈𝗐 𝑎 𝗍𝗈𝖼𝗈𝗇𝗍(𝐽′)⟶∗𝐽′◃𝑎⟶𝐽◃𝗂𝗇𝗅𝑎⟶𝐾▹𝑎⟶𝐾◃𝑎. The case-frame translation is 𝐽𝗄ℎ=𝜆𝑠.𝖼𝖺𝗌𝖾 𝑠 𝗈𝖿{𝗂𝗇𝗅𝑥↦𝑥𝖼𝐾𝗄ℎ;𝗂𝗇𝗋𝑞↦(𝗍𝗁𝗋𝗈𝗐 𝑎 𝗍𝗈 𝑞)𝖼𝐾𝗄ℎ}, and the restored injection frame is 𝐽′ℎ𝗄 =𝜆𝑏.𝐽𝗄ℎ(𝗂𝗇𝗅 𝑏). The CPS normal form from the preceding solution first supplies 𝗂𝗇𝗋(𝐽′ℎ𝗄) to 𝐽𝗄ℎ; the right branch applies 𝐽′ℎ𝗄 to 𝑎𝗏, after which the injection continuation calls 𝐽𝗄ℎ again with 𝗂𝗇𝗅 𝑎𝗏. The left branch then calls 𝐾𝗄ℎ𝑎𝗏, the translation of the endpoint.
exercise 35.11.
Let 𝐷={𝑓,𝑟.𝑓𝑟; 𝑥.𝖣𝖧(𝑒𝑟)},𝑣𝑐=𝜆𝑧.𝗁𝖺𝗇𝖽𝗅𝖾 𝖣𝖧(𝐸)[𝑧]𝐷. Then the entire root calculation is 𝖣𝖧(⟨𝐸[𝗌𝗁𝗂𝖿𝗍0 𝑘.𝑒]∣𝑥.𝑒𝑟⟩)=𝗁𝖺𝗇𝖽𝗅𝖾 𝖣𝖧(𝐸)[𝖽𝗈(𝜆𝑘.𝖣𝖧(𝑒))]𝐷⟶(𝜆𝑘.𝖣𝖧(𝑒))𝑣𝑐⟶𝛽𝖣𝖧(𝑒)[𝑣𝑐/𝑘]=𝖣𝖧(𝑒[(𝜆𝑧.⟨𝐸[𝑧]∣𝑥.𝑒𝑟⟩)/𝑘]). The first contraction is legal only because 𝐸 is 0-free. Translation preserves freeness, so the deep handler sees the translated operation before any nearer delimiter. The last equality uses translation of plugging and value substitution; it is not an extra reduction.
exercise 35.12.
Choose a target value 𝑢 and define 𝑇(𝑠) =𝑢 for every source state. For each source step 𝑠 →𝑠′, one has 𝑇(𝑠) =𝑢 =𝑇(𝑠′), hence 𝑇(𝑠) →∗𝑇(𝑠′) by the empty target reduction. Nevertheless an infinite source run 𝑠0 →𝑠1 →⋯ translates to the constant sequence 𝑢,𝑢,…, not to an infinite target reduction. Target strong normalization says nothing about repetitions joined by zero steps.
In theorem 35.13, positivity is used when the per-source-step reductions are concatenated: 𝑇(𝑠0)→+𝑇(𝑠1)→+𝑇(𝑠2)→+⋯. Because every segment contains at least one target step, infinitely many source steps yield infinitely many target steps, contradicting target strong normalization. Replacing →+ by →∗ invalidates exactly that inference.
exercise 35.13.
Under the value-restricted grammar, 𝑝0 is not a proof value: its outer constructor is 𝖼𝖺𝗅𝗅𝖼𝖼. Consequently both 𝗐𝗂𝗍𝑝0and𝗉𝗋𝖿𝑝0 are ill formed. The first was needed to commute projection through control and to convert it to 0; the second was needed for the certificate 𝗐𝗂𝗍 𝑝0 =1. Hence the two premises of Dep-Subst cannot be assembled and this inconsistency derivation is blocked.
This syntactic observation is not a soundness theorem. A complete dependent control calculus must still define every evaluation context and conversion, prove substitution and preservation for all of them, and show that no other eliminator observes a nonvalue computation in a dependent type. The value restriction removes this counterexample; it does not supply those missing metatheoretic arguments.