Prerequisites. Direct starred prerequisites: none. No later core chapter depends on this route.
Let 𝗋𝖾𝖺𝖽:𝐹𝖭𝖺𝗍 be the state-reading computation of chapter 22. An ordinary monadic bind can form 𝗋𝖾𝖺𝖽𝗍𝗈𝑥𝗂𝗇𝗋𝖾𝗍𝗎𝗋𝗇𝑥:𝐹𝖭𝖺𝗍. It cannot assign the result the family 𝐹(𝖵𝖾𝖼𝖡𝗈𝗈𝗅𝑥), because 𝑥 is not in scope in the type of the whole computation. Substituting the effectful term 𝗋𝖾𝖺𝖽 into that family is worse: another read may produce another number. The defect is not missing notation. Dependency needs a stable value, whereas the operation has not yet produced one.
Fix a universe 𝖴 containing a Boolean type 𝖡, a unit type 𝟏, and an empty type ⊥. There are closed terms 𝗍𝗋𝗎𝖾,𝖿𝖺𝗅𝗌𝖾:𝖡 and 𝗎𝗇𝗂𝗍:𝟏. The universe is closed under dependent products and binary products: Γ⊢𝐴:𝖴Γ,𝑥:𝐴⊢𝐵:𝖴Γ⊢Π𝑥:𝐴𝐵:𝖴,Γ⊢𝐴:𝖴Γ⊢𝐵:𝖴Γ⊢𝐴×𝐵:𝖴. Products have pairing and projections with their beta equations; dependent products have lambda abstraction, application, and beta conversion. Write 𝐴→𝐵 for Π_:𝐴𝐵, and write Γ⊢⋆:𝐴 when 𝐴 is inhabited. No identity type, extensionality principle, or effect equation is assumed by the argument below.
is admissible, and when the same case analysis is available one level up: from Γ⊢𝐴𝗍:𝖴 and Γ⊢𝐴𝖿:𝖴 one may form a family Γ,𝑥:𝖡⊢𝐴:𝖴 with 𝐴[𝗍𝗋𝗎𝖾/𝑥]≡𝐴𝗍 and 𝐴[𝖿𝖺𝗅𝗌𝖾/𝑥]≡𝐴𝖿. The second clause is what makes the rule an induction principle rather than a proof of two cases; the proof below uses it once, to build a predicate. It has an observable effect when there are a closed 𝑡:𝖡 and a one-hole context 𝐶[−] such that 𝐶[𝗍𝗋𝗎𝖾]≡𝗍𝗋𝗎𝖾,𝐶[𝖿𝖺𝗅𝗌𝖾]≡𝗍𝗋𝗎𝖾,𝐶[𝑡]≡𝖿𝖺𝗅𝗌𝖾. This observability premise is stronger than merely having an operation. Printing, an unhandled exception, and divergence need not provide such a Boolean discriminator inside the theory.
Proof. Write 𝑋↔𝑌 for the pair of functions (𝑋→𝑌)×(𝑌→𝑋), and define Leibniz equality at type 𝐴 by 𝑎=𝐴𝑏:=Π𝑃:𝐴→𝖴.𝑃𝑎↔𝑃𝑏. Let 𝑡 and 𝐶[−] witness observability. Apply dependent Boolean elimination to the family 𝐶[𝑥]=𝖡𝗍𝗋𝗎𝖾. Its two branches are inhabited because both 𝐶[𝗍𝗋𝗎𝖾] and 𝐶[𝖿𝖺𝗅𝗌𝖾] are judgmentally true. Thus 𝑥:𝖡⊢⋆:𝐶[𝑥]=𝖡𝗍𝗋𝗎𝖾. Substitution at 𝑡 gives ⊢⋆:𝐶[𝑡]=𝖡𝗍𝗋𝗎𝖾. Conversion along 𝐶[𝑡]≡𝖿𝖺𝗅𝗌𝖾 gives ⊢⋆:𝖿𝖺𝗅𝗌𝖾=𝖡𝗍𝗋𝗎𝖾.
It remains to turn that equality into an inhabitant of ⊥. The second clause of definition 103.2 builds the family 𝑥:𝖡⊢𝑃:𝖴 determined by 𝑃[𝖿𝖺𝗅𝗌𝖾/𝑥]≡⊥,𝑃[𝗍𝗋𝗎𝖾/𝑥]≡𝟏, and this is the only step that needs case analysis at the universe. Instantiating the Leibniz equality at 𝑃 gives ⋆:⊥↔𝟏; applying its second component to 𝗎𝗇𝗂𝗍:𝟏 produces an inhabitant of ⊥. ◻
In call by value, beta substitution is restricted to values, so the first vertex is weakened. In call by name, arbitrary substitution remains, but a dependent eliminator must force the scrutinee in its classifier as well as its term; unrestricted elimination is weakened. These are exact exits from the theorem, not evaluation-order slogans.
★★☆ Delete the contextual equation 𝐶[𝑡]≡𝖿𝖺𝗅𝗌𝖾 from definition 103.2. Locate the first conversion in the proof of theorem 103.3 that can no longer be derived. Explain why a diverging Boolean term need not restore that equation.
Call-by-push-value prevents an effectful computation from occupying a value variable. Chapter 22 fixes the nondependent calculus; this chapter states one delta against that signature and then proves at the enlarged one.
The delta has three parts. First, the type formers Σ and Π become dependent, so a value type may mention a value variable: 𝐴::=𝟏∣𝖡∣Σ𝑥:𝐴𝐵∣𝑈𝐵――,𝐵――::=𝐹𝐴∣Π𝑥:𝐴𝐵――,𝑉::=𝑥∣𝗎𝗇𝗂𝗍∣(𝑉,𝑊)∣𝗍𝗁𝗎𝗇𝗄𝑀,𝑀::=𝗋𝖾𝗍𝗎𝗋𝗇𝑉∣𝖿𝗈𝗋𝖼𝖾𝑉∣𝜆𝑥.𝑀∣𝑀𝑉∣𝑀𝗍𝗈𝑥𝗂𝗇𝑁∣𝖽𝗂𝗏𝖾𝗋𝗀𝖾𝐵――∣𝜇𝐵――𝑧𝑀∣𝗐𝗋𝗂𝗍𝖾𝑠.𝑀∣𝗋𝖾𝖺𝖽𝗍𝗈𝑠(𝑀𝑠)∣𝗉𝗋𝗂𝗇𝗍𝑚.𝑀∣𝖼𝗁𝗈𝗈𝗌𝖾𝑖(𝑀𝑖)∣𝖾𝗋𝗋𝗈𝗋𝐵――𝑒. Second, the seven operation forms are carried over unchanged from chapter 22. Their complete typing delta is
Γ⊢𝖼𝖽𝗂𝗏𝖾𝗋𝗀𝖾𝐵――:𝐵――
Diverge
Γ,𝑧:𝑈𝐵――⊢𝖼𝑀:𝐵――
Γ⊢𝖼𝜇𝐵――𝑧𝑀:𝐵――
Rec
Γ⊢𝖼𝖾𝗋𝗋𝗈𝗋𝐵――𝑒:𝐵――
Error
Γ⊢𝖼𝑀:𝐵――
Γ⊢𝖼𝗐𝗋𝗂𝗍𝖾𝑠.𝑀:𝐵――
Write
Γ⊢𝖼𝑀:𝐵――
Γ⊢𝖼𝗉𝗋𝗂𝗇𝗍𝑚.𝑀:𝐵――
Print
{Γ⊢𝖼𝑀𝑖:𝐵――}1≤𝑖≤𝑛
Γ⊢𝖼𝖼𝗁𝗈𝗈𝗌𝖾𝑖(𝑀𝑖):𝐵――
Choose
{Γ⊢𝖼𝑀𝑠:𝐵――}𝑠∈𝑆
Γ⊢𝖼𝗋𝖾𝖺𝖽𝗍𝗈𝑠(𝑀𝑠):𝐵――
Read
Here 𝑠∈𝑆 ranges over a finite pointed state set, 𝑚∈M over a printing monoid, and 𝑒∈𝐸 over errors. The annotations on divergence, recursion, and error record the computation type that their premise does not otherwise determine. Recursion unfolding is included in judgmental equality: 𝜇𝐵――𝑧𝑀≡𝑀[𝗍𝗁𝗎𝗇𝗄(𝜇𝐵――𝑧𝑀)/𝑧]. The computation 𝗋𝖾𝖺𝖽 of the opening is 𝗋𝖾𝖺𝖽𝗍𝗈𝑠(𝗋𝖾𝗍𝗎𝗋𝗇𝑠). Third, the sequencing rule itself changes, and that change is the subject of the chapter.
The judgments are Γ⊢𝗏𝑉:𝐴, Γ⊢𝖼𝑀:𝐵――, and separate formation judgments for value and computation types. Contexts contain only value variables.
The expression 𝗋𝖾𝗍𝗎𝗋𝗇3𝗍𝗈𝑥𝗂𝗇𝗋𝖾𝗍𝗎𝗋𝗇(𝗋𝖾𝗉𝗅𝗂𝖼𝖺𝗍𝖾𝑥𝗍𝗋𝗎𝖾) computes to a length-three vector. Rule Bind− can type its term but cannot expose that length in the classifier of the whole computation. This is the concrete obstruction that forces the plus calculus.
For the vector computation, fix a value-type family 𝖱𝖾𝗌𝗎𝗅𝗍𝖵𝖾𝖼:𝑈𝐹𝖭𝖺𝗍→𝖴 with defining equation 𝖱𝖾𝗌𝗎𝗅𝗍𝖵𝖾𝖼(𝗍𝗋𝑛)≡𝖵𝖾𝖼𝖡𝑛. Then form 𝐵――(𝑧):=𝐹(𝖱𝖾𝗌𝗎𝗅𝗍𝖵𝖾𝖼(𝑧)). The family is a value-level classifier; it does not force 𝑧 as a computation. The result type stores 𝗍𝗁𝗎𝗇𝗄𝑀, so repeated type inspection does not rerun 𝑀.
Work one effectful program at that classifier. Let 𝑆={0,1,2} be the state set, let 𝑀:=𝗋𝖾𝖺𝖽𝗍𝗈𝑠(𝗋𝖾𝗍𝗎𝗋𝗇𝑠):𝐹𝖭𝖺𝗍 read the cell, and let 𝑁:=𝗋𝖾𝗍𝗎𝗋𝗇(𝗋𝖾𝗉𝗅𝗂𝖼𝖺𝗍𝖾𝑥𝗍𝗋𝗎𝖾). Rule Bind+ types 𝑀𝗍𝗈𝑥𝗂𝗇𝑁 at 𝐵――[𝗍𝗁𝗎𝗇𝗄𝑀/𝑧]=𝐹(𝖱𝖾𝗌𝗎𝗅𝗍𝖵𝖾𝖼(𝗍𝗁𝗎𝗇𝗄𝑀)). The postcondition genuinely depends on the returned value: in state 𝑠 the program returns a vector of length 𝑠, and the classifier names the computation that produced it rather than any one of those lengths. Nothing here forces 𝑀: the classifier inspects 𝗍𝗁𝗎𝗇𝗄𝑀, so type checking the program does not read the cell. What the classifier cannot do is reduce to 𝖵𝖾𝖼𝖡2 in state 2, because 𝖱𝖾𝗌𝗎𝗅𝗍𝖵𝖾𝖼 computes only on 𝗍𝗋𝑛.
Recovering it means running the machine, and that is where this program leaves the equality-preserving fragment. The transition from the state read 𝑀 to its selected branch 𝑀𝑠 is not a judgmental equality, so a classifier that distinguishes their thunks changes across the step. Rule Bind+ still types the source program. The base preservation claim cannot cover its read step; the extended claim below uses an explicit computation-type inclusion to retype the selected branch at the source read classifier. Replacing the cell by a fixed environment removes the problem and the effect together: with 𝑀𝑒:=𝗋𝖾𝗍𝗎𝗋𝗇𝑒 under a parameter 𝑒:𝐸, the classifier may name 𝑒 itself, no transition of the machine fires, and the first claim applies unchanged.
Let Γ,𝑧:𝑈𝐹𝐴⊢𝐵――(𝑧)𝖼𝗍𝗒𝗉𝖾. A computation 𝑀:𝐹𝐴 is thunkable for 𝐵―― when every step 𝑀⟶𝑀′ satisfies 𝐵――[𝗍𝗁𝗎𝗇𝗄𝑀/𝑧]≡𝐵――[𝗍𝗁𝗎𝗇𝗄𝑀′/𝑧]. Let 𝑀:𝐹𝐴, 𝑁:𝐹𝐴′, and let 𝐾(𝑥,𝑦) be a well-typed continuation with 𝑥∉FV(𝑁) and 𝑦∉FV(𝑀). The continuation is linear for 𝑀,𝑁 when the interchange equation 𝑀𝗍𝗈𝑥𝗂𝗇(𝑁𝗍𝗈𝑦𝗂𝗇𝐾)≡𝑁𝗍𝗈𝑦𝗂𝗇(𝑀𝗍𝗈𝑥𝗂𝗇𝐾) holds at their common computation type. Both are properties of the printed family, computations, and continuation; neither is a typing judgment that every effect automatically satisfies, and neither is a notion of the selected source, which classifies effects by a different criterion recorded in lemma 103.9 below. They are used here only to sort effects, never as an unstated hypothesis of a theorem.
Sort the seven operations, and note at once that the sort does not follow intuition about which effects feel harmless. 𝖾𝗋𝗋𝗈𝗋 is thunkable vacuously: it has no successor, so the quantification over steps is empty. Divergence is thunkable because its only successor is itself. Recursion is thunkable when its unfolding equation is included in judgmental equality. Each of 𝗐𝗋𝗂𝗍𝖾, 𝗉𝗋𝗂𝗇𝗍, 𝖼𝗁𝗈𝗈𝗌𝖾, and 𝗋𝖾𝖺𝖽𝗍𝗈 fails thunkability for any family that distinguishes its source thunk from the thunk of the selected successor.
The last of those deserves its own sentence, because reading looks passive. It is not. 𝗋𝖾𝖺𝖽𝗍𝗈𝑠(𝑀𝑠) does not compute a value from its own subterms; it selects the branch 𝑀𝑠 indexed by the state the machine happens to be in, and that state is not part of the term. Two runs of the same closed computation therefore take different transitions, so no equation of the calculus can identify 𝗋𝖾𝖺𝖽𝗍𝗈𝑠(𝑀𝑠) with the branch it selects. Reading is the read half of global state, and it is excluded from the first theorem below exactly as writing is.
A reader—a computation parameterized by an environment that is never written—is a different object, and it is not an effect of this calculus at all. Fix a value type 𝐸 of environments and use a value parameter: Π𝑒:𝐸𝐹𝐴 is an ordinary dependent computation type built from Bind− and Bind+, its classifier may mention 𝑒 directly rather than a thunk, and no transition of definition 103.8 fires for it. The distinction is exactly the one Bind+ was introduced to make: a value already produced may be named in a type, a computation that has not run may not.
★★☆ Instantiate Bind+ with a closed 𝑀:𝐹𝖭𝖺𝗍 and the vector family above. Write the context and classifier before and after the beta step at 𝑀=𝗋𝖾𝗍𝗎𝗋𝗇2. Explain why replacing 𝗍𝗁𝗎𝗇𝗄𝑀 by 𝑀 is ill sorted.
Proof. Prove the four claims simultaneously by induction on their derivations. A variable derivation for 𝑥 becomes the given derivation of 𝑉; every other variable is unchanged. Under Σ, Π, and lambda binders, choose 𝑦∉FV(𝑉)∪dom(Γ) and apply the induction hypothesis to the alpha-renamed body.
For Bind+, write its two bound names as 𝑥0, the value variable of 𝗍𝗈𝑥0𝗂𝗇, and 𝑧, the thunk variable of the classifier; alpha-rename both outside FV(𝑉)∪{𝑥}. Substitute in the family formation premise, the computation premise, and the continuation premise. The two substitutions then commute, because no bound name of the rule occurs in 𝑉 and 𝑥 is neither 𝑥0 nor 𝑧. Thus 𝐵――[𝗍𝗁𝗎𝗇𝗄𝑀/𝑧][𝑉/𝑥]=𝐵――[𝑉/𝑥][𝗍𝗁𝗎𝗇𝗄(𝑀[𝑉/𝑥])/𝑧], which is the conclusion classifier of the rebuilt rule. Return, thunk, force, ordinary bind, products, and their equations rebuild their induction hypotheses directly. Conversion substitutes into both sides of the equality derivation. These are all rule families of the displayed fragment. ◻
Subject reduction is stated for a machine rather than a term relation, because a dependent classifier is disturbed by what the surrounding stack does, not only by what the head computation does.
A stackΓ;𝐵――⊢𝗄𝐾:𝐶―― takes a computation of type 𝐵―― to one of type 𝐶――. Stacks are generated by
Γ;𝐶――⊢𝗄𝗇𝗂𝗅:𝐶――
Nil
Γ,𝑥:𝐴⊢𝖼𝑀:𝐵――Γ;𝐵――⊢𝗄𝐾:𝐶――
Γ;𝐹𝐴⊢𝗄([⋅]𝗍𝗈𝑥𝗂𝗇𝑀)::𝐾:𝐶――
To
Γ⊢𝗏𝑉:𝐴Γ;𝐵――[𝑉/𝑥]⊢𝗄𝐾:𝐶――
Γ;Π𝑥:𝐴𝐵――⊢𝗄𝑉::𝐾:𝐶――
Arg
A configuration is a pair 𝑀,𝐾 of a computation Γ⊢𝖼𝑀:𝐵―― and a stack Γ;𝐵――⊢𝗄𝐾:𝐶――; its type is 𝐶――. On the displayed term fragment, the pure transitions are (𝑀𝑉,𝐾)⟶(𝑀,𝑉::𝐾),(𝜆𝑥.𝑀,𝑉::𝐾)⟶(𝑀[𝑉/𝑥],𝐾),(𝑀𝗍𝗈𝑥𝗂𝗇𝑁,𝐾)⟶(𝑀,([⋅]𝗍𝗈𝑥𝗂𝗇𝑁)::𝐾),(𝗋𝖾𝗍𝗎𝗋𝗇𝑉,([⋅]𝗍𝗈𝑥𝗂𝗇𝑁)::𝐾)⟶(𝑁[𝑉/𝑥],𝐾),(𝖿𝗈𝗋𝖼𝖾(𝗍𝗁𝗎𝗇𝗄𝑀),𝐾)⟶(𝑀,𝐾),(𝖽𝗂𝗏𝖾𝗋𝗀𝖾𝐵――,𝐾)⟶(𝖽𝗂𝗏𝖾𝗋𝗀𝖾𝐵――,𝐾),(𝜇𝐵――𝑧𝑀,𝐾)⟶(𝑀[𝗍𝗁𝗎𝗇𝗄(𝜇𝐵――𝑧𝑀)/𝑧],𝐾),(𝖼𝗁𝗈𝗈𝗌𝖾𝑖(𝑀𝑖),𝐾)⟶(𝑀𝑗,𝐾)(1≤𝑗≤𝑛). Every (𝖾𝗋𝗋𝗈𝗋𝐵――𝑒,𝐾) is terminal. For printing and global state, a configuration carries two further components, an output 𝑚 and a state 𝑠, and the transitions are (𝗐𝗋𝗂𝗍𝖾𝑠′.𝑀,𝐾,𝑚,𝑠)⟶(𝑀,𝐾,𝑚,𝑠′),(𝗋𝖾𝖺𝖽𝗍𝗈𝑠′(𝑀𝑠′),𝐾,𝑚,𝑠)⟶(𝑀𝑠,𝐾,𝑚,𝑠),(𝗉𝗋𝗂𝗇𝗍𝑛.𝑀,𝐾,𝑚,𝑠)⟶(𝑀,𝐾,𝑚∗𝑛,𝑠). All pure transitions preserve 𝑚 and 𝑠. Initial configurations use the monoid unit and the pointed initial state; terminal configurations may carry any output and state.
Let Γ,𝑧:𝑈𝐹𝐴⊢𝐵――𝖼𝗍𝗒𝗉𝖾. If 𝑀≡𝑀′:𝐹𝐴, then 𝐵――[𝗍𝗁𝗎𝗇𝗄𝑀/𝑧]≡𝐵――[𝗍𝗁𝗎𝗇𝗄𝑀′/𝑧]. Call 𝐵――sensitive to a transition(𝑀,𝐾)⟶(𝑀′,𝐾) when the displayed equality fails. Force/thunk beta, recursion unfolding, and the self-loop of divergence are insensitive for every well-formed 𝐵――. The operational rules for writing, printing, choice, and reading provide no such judgmental equality; a family that distinguishes their two thunks is therefore sensitive to that step.
Proof of Lemma 103.9 — Equality-preserved classifiers
Proof. Congruence first gives 𝗍𝗁𝗎𝗇𝗄𝑀≡𝗍𝗁𝗎𝗇𝗄𝑀′. Substitution respects judgmental equality, which gives the displayed classifier equality. The force/thunk and recursion transitions are directed uses of their judgmental equations, and divergence has identical source and target, proving the three uniform claims.
No converse is asserted for an arbitrary family: a constant family cannot observe any transition. For a sensitive family, failure of the classifier equality is its defining property. A write or print step discards its outer operation, while a choice or read step selects one branch; none of these four root transitions is a judgmental equation of the selected signature. The inclusion rules in theorem 103.10 handle exactly these steps without pretending that all families distinguish them. ◻
In absence of printing, global state, and erratic choice, every transition of the machine of definition 103.8 from a well-typed configuration results in a well-typed configuration of the same type. If the four computation-type inclusion rules
Γ⊢𝖼𝑁:𝐵――[𝗍𝗁𝗎𝗇𝗄𝑀/𝑧]
Γ⊢𝖼𝑁:𝐵――[𝗍𝗁𝗎𝗇𝗄(𝗐𝗋𝗂𝗍𝖾𝑠.𝑀)/𝑧]
Incl-Write
Γ⊢𝖼𝑁:𝐵――[𝗍𝗁𝗎𝗇𝗄𝑀𝑠′/𝑧]
Γ⊢𝖼𝑁:𝐵――[𝗍𝗁𝗎𝗇𝗄(𝗋𝖾𝖺𝖽𝗍𝗈𝑠(𝑀𝑠))/𝑧]
Incl-Read
Γ⊢𝖼𝑁:𝐵――[𝗍𝗁𝗎𝗇𝗄𝑀/𝑧]
Γ⊢𝖼𝑁:𝐵――[𝗍𝗁𝗎𝗇𝗄(𝗉𝗋𝗂𝗇𝗍𝑚.𝑀)/𝑧]
Incl-Print
Γ⊢𝖼𝑁:𝐵――[𝗍𝗁𝗎𝗇𝗄𝑀𝑖′/𝑧]
Γ⊢𝖼𝑁:𝐵――[𝗍𝗁𝗎𝗇𝗄(𝖼𝗁𝗈𝗈𝗌𝖾𝑖(𝑀𝑖))/𝑧]
Incl-Choose
are added, for every 𝑠′∈𝑆 and 1≤𝑖′≤𝑛, then the same holds even with printing, global state, and erratic choice. Both claims are at the displayed value/computation syntax, the seven operation-typing rules, the recursion equation, and the transitions of definition 103.8; they assert neither normalization nor decidable conversion.
Proof. Fix a transition from a configuration of result type 𝐶――, and induct on the root transition. The induction invariant retains a middle computation type 𝐵――: before and after the transition, the head has type 𝐵―― and the stack consumes 𝐵――, up to the conversion rule in the first claim and up to one of the four displayed inclusions in the second claim.
For application push, inversion gives Γ⊢𝖼𝑀:Π𝑥:𝐴𝐵――, Γ⊢𝗏𝑉:𝐴, and a stack consuming 𝐵――[𝑉/𝑥]. Rule Arg therefore types 𝑉::𝐾 as a stack consuming Π𝑥:𝐴𝐵――. Lambda pop uses value substitution on the premise Γ,𝑥:𝐴⊢𝖼𝑀:𝐵――, yielding Γ⊢𝖼𝑀[𝑉/𝑥]:𝐵――[𝑉/𝑥]; the tail stack already consumes that type. Force/thunk contraction is typed by inversion of Force and Thunk. Divergence is a self-loop at its annotation, and recursion unfolding is typed by substituting 𝗍𝗁𝗎𝗇𝗄(𝜇𝐵――𝑧𝑀):𝑈𝐵―― for 𝑧 in the premise of Rec. An error configuration has no successor.
For sequencing push, inversion of Bind− or Bind+ gives the head typing and the frame premise. Rule To rebuilds the stack in the minus case. In the plus case, retain the classifier family Γ,𝑧:𝑈𝐹𝐴,Γ′⊢𝐵――(𝑧)𝖼𝗍𝗒𝗉𝖾 as part of the frame invariant. When the head reaches 𝗋𝖾𝗍𝗎𝗋𝗇𝑉, value substitution gives Γ,Γ′[𝗍𝗋𝑉/𝑧]⊢𝖼𝑁[𝑉/𝑥]:𝐵――[𝗍𝗋𝑉/𝑧]. Every intervening transition in the first claim is a directed judgmental equation: beta, force/thunk, recursion unfolding, or the divergence self-loop. Consequently 𝑀≡𝗋𝖾𝗍𝗎𝗋𝗇𝑉, and lemma 103.9 gives 𝐵――[𝗍𝗁𝗎𝗇𝗄𝑀/𝑧]≡𝐵――[𝗍𝗋𝑉/𝑧]. Conversion therefore makes the residual head and tail stack meet at the original middle type. This proves the two sequencing roots, including the only case in which the middle type can mention the computation being run.
It remains to check the four observable roots admitted only by the second claim. Inverting Write and Print types the successor 𝑀 at 𝐵――[𝗍𝗁𝗎𝗇𝗄𝑀/𝑧]; Incl-Write or Incl-Print converts that judgment to the classifier containing the discarded outer operation. Inverting Read or Choose types every branch, in particular the selected branch 𝑀𝑠′ or 𝑀𝑖′, and Incl-Read or Incl-Choose converts the selected classifier to the source classifier. The output and state components do not occur in typing, so their update leaves the derivation unchanged. These four roots and the pure roots listed in definition 103.8 exhaust the machine. Hence the first claim holds without the four roots, and the second holds after adding their inclusions. ◻
The exclusions are substantive. Each of the four excluded operations replaces the term by a successor that judgmental equality need not identify with it. A family sensitive in the sense of lemma 103.9 therefore has different classifiers before and after the step. A write and a print discard an outer operation; a choice and a read select a branch on information the term does not contain. The inclusion rules of the second claim repair this by giving up uniqueness of typing rather than by proving the two types equal. Thunkability, in the sense of definition 103.6, is the corresponding property of one computation and one family; it is not a theorem that all state computations are harmless.
Translations and two bounded repairs
The call-by-value translation sends a source type 𝐴 to a value type 𝐴𝗏 and a term to a computation 𝑀𝗏:𝐹𝐴𝗏. A source variable remains a value, so substitution is restricted to values. The call-by-name translation sends a source type to a computation type and places assumptions under 𝑈; arbitrary substitution is available, while dependent elimination requires the storage/thunkability equation. Neither translation validates all three vertices of theorem 103.3.
Classical control produces another concrete failure, and it is worth printing because the repair is the same move as Bind+ made at a different level. Under the ordinary double-negation translation a computation of type 𝐴 becomes (𝐴+→⊥)→⊥. The type of the second component of a dependent pair must then mention 𝖿𝗌𝗍𝑒, a value that exists only inside a continuation and can never be returned, since the continuation’s answer type is ⊥.
A polymorphic-answer CPS translation changes the answer type from ⊥ to a variable. Its computation translation is 𝐴÷:=Π𝛼:∗.(𝐴+→𝛼)→𝛼, so that the underlying value can be extracted by running the computation at the identity continuation: 𝑒÷𝐴+𝗂𝖽:𝐴+. Two target rules make that extraction usable inside a type. The first records the value of a computation while checking a continuation,
Γ⊢𝑒:Π𝛼:∗.(𝐴→𝛼)→𝛼Γ⊢𝐵:∗Γ,𝑥=𝑒𝐴𝗂𝖽⊢𝑒′:𝐵
Γ⊢𝑒@𝐵(𝜆𝑥:𝐴.𝑒′):𝐵
T-Cont
and the second is the equation that justifies it, Γ⊢(𝑒1@𝐵(𝜆𝑥:𝐴.𝑒2))≡(𝜆𝑥:𝐴.𝑒2)(𝑒1𝐴𝗂𝖽). Evaluation order is explicit in T-Cont: the continuation body 𝑒′ is checked under the hypothesis that 𝑥 already equals the value that 𝑒 returns, so the pair’s second component may mention it. Compare Bind+, which checks 𝑁 under a classifier mentioning 𝗍𝗋𝑥 for the value 𝑥 that 𝑀 will return. Both rules buy dependency by naming the not-yet-produced value in the classifier; the source language differs, and so does what is proved. Its call-by-name and call-by-value translations preserve typing for the exact CoC-with-Π/Σ signatures of those translations. This fact does not prove that arbitrary control operators satisfy Bind+.
A fibred calculus repairs the same obstruction with a different rule. It adds a computational Sigma type: from Γ,𝑥:𝐴⊢𝐶―― it forms Γ⊢Σ𝑥:𝐴𝐶――, a computation type whose inhabitants package a value index with a computation in the corresponding fiber. Its introduction and elimination are ⟨𝑉,𝑀⟩(𝑥:𝐴).𝐶――,𝑀𝗍𝗈⟨𝑥:𝐴,𝑧:𝐶――⟩𝗂𝗇𝐾, and the eliminator is typed in a third judgment Γ∣𝑧:𝐶――⊢𝐾:𝐷―― of homomorphism terms, in which the computation variable 𝑧 occurs linearly. That linearity is what fixes evaluation order: a computation bound to 𝑧 always runs before the rest of 𝐾, so eliminating ⟨𝑉,𝑀⟩ runs 𝑀 first.
The two repairs differ in where the not-yet-produced value is named. Bind+ keeps one judgment and moves the dependency into the classifier through a thunk; the fibred calculus adds a judgment and moves the dependency into a linear computation variable. On the vector example the package contains 𝑛:𝖭𝖺𝗍 and a computation returning 𝖵𝖾𝖼𝖡𝑛, and no thunk appears. The rule delta has a different semantic model and donates no substitution or preservation theorem to definition 103.5.
Suggested first pass.
None of these problems is a prerequisite for a later chapter. Begin with exercise 103.3, then complete exercise 103.5.
★★☆ Reconstruct the Fire Triangle proof using an identity type instead of Leibniz equality. State the eliminator used to distinguish true from false and identify the conversion that uses observability.
★★★ Classify 𝖾𝗋𝗋𝗈𝗋, 𝗐𝗋𝗂𝗍𝖾, 𝗋𝖾𝖺𝖽𝗍𝗈, 𝖼𝗁𝗈𝗈𝗌𝖾, and a fixed-environment reader against thunkability. For each positive classification write the equation required by definition 103.6; for each negative one give a family 𝐵――(𝑧) and two states, or two branches, at which the two classifiers differ. Then say which of the five are admitted by the first claim of theorem 103.10 and which need an inclusion rule, and explain why the reader is on the admitted side for a reason that has nothing to do with thunkability.
★★★Practical project.dcbpv-dependent-sequencing-checker Implement in Kappa a finite checker and evaluator for values, computations, return, thunk, force, a state read, and dependent sequencing over natural-indexed vectors. Maintain the invariant that classifiers mention only value variables or thunks admitted by Bind+, so that sequencing a state read yields a classifier that names the thunk rather than any one state. The named acceptance cases are 𝚛𝚎𝚝𝚞𝚛𝚗-𝚟𝚎𝚌𝚝𝚘𝚛-𝟸↦𝚊𝚌𝚌𝚎𝚙𝚝𝚎𝚍:𝚅𝚎𝚌𝟸,𝚛𝚊𝚠-𝚎𝚏𝚏𝚎𝚌𝚝-𝚒𝚗-𝚝𝚢𝚙𝚎↦𝚛𝚎𝚓𝚎𝚌𝚝𝚎𝚍:𝚌𝚘𝚖𝚙𝚞𝚝𝚊𝚝𝚒𝚘𝚗𝚒𝚗𝚟𝚊𝚕𝚞𝚎𝚙𝚘𝚜𝚒𝚝𝚒𝚘𝚗,𝚏𝚘𝚛𝚌𝚎-𝚗𝚎𝚞𝚝𝚛𝚊𝚕↦𝚗𝚎𝚞𝚝𝚛𝚊𝚕𝚌𝚘𝚖𝚙𝚞𝚝𝚊𝚝𝚒𝚘𝚗,𝚛𝚎𝚊𝚍𝚝𝚘-𝚌𝚕𝚊𝚜𝚜𝚒𝚏𝚒𝚎𝚛↦𝚊𝚌𝚌𝚎𝚙𝚝𝚎𝚍:𝚝𝚑𝚞𝚗𝚔𝚎𝚍. A mutation that permits a raw computation in a classifier must fail the second oracle, and one that collapses a state read to a single state must fail the fourth. The checker illustrates subject reduction on a finite fragment; it does not prove the Fire Triangle or semantic soundness.
Sources. The no-go theorem and its CBV/CBN boundary are reconstructed from Pédrot and Tabareau, pp. 2–5 [PT20]. The dCBPV split, dependent Kleisli extension, translations, and effect-specific preservation boundary follow Vákár [Vá15]: the effect operations and their machine transitions are his Figures 8–10, the dependently typed stacks and configurations of definition 103.8 are his Figure 21, subject reduction is his Theorem 3.10, and the inclusion rules that recover it for printing, global state, and erratic choice are his Figure 24 and Theorem 3.11. Neither that paper nor his thesis uses the words thunkable and linear; definition 103.6 is chapter-local and is used only to sort effects. The CPS comparison is source-bounded to Bowman et al., whose answer-type-polymorphic computation translation and T-Cont rule are printed on their p. 22:8 [BCRA18]; the computational-Sigma comparison is source-bounded to Ahman, Ghani, and Plotkin, whose computation-term grammar and homomorphism judgment are their Figure 1 [AGP16].