Prerequisites. Direct starred prerequisites: none. No later core chapter depends on this route.
Let 𝖺𝗌𝗄:1→𝖨𝗇𝗍 be an operation. Two handlers implement it: 𝐻𝗈𝗎𝗍(())=7,𝐻𝗂𝗇(())=9. A library function receives a suspended computation 𝑞 and evaluates it under the inner handler: 𝗎𝗇𝖽𝖾𝗋𝖨𝗇𝗇𝖾𝗋(𝑞):=𝗁𝖺𝗇𝖽𝗅𝖾𝐻𝗂𝗇(𝑞()). Suppose 𝑞 is defined while the outer handler is in scope: 𝗁𝖺𝗇𝖽𝗅𝖾𝐻𝗈𝗎𝗍(𝗅𝖾𝗍𝑞=𝜆().𝖺𝗌𝗄()𝗂𝗇𝗎𝗇𝖽𝖾𝗋𝖨𝗇𝗇𝖾𝗋(𝑞)). In the minimal nearest-name model, beta reduction exposes the request under the inner handler; nearest-name dispatch makes the inner clause answer it. Thus the initial program and its result are 𝗁𝖺𝗇𝖽𝗅𝖾𝐻𝗈𝗎𝗍(𝗅𝖾𝗍𝑞=𝜆().𝖺𝗌𝗄()𝗂𝗇𝗁𝖺𝗇𝖽𝗅𝖾𝐻𝗂𝗇(𝑞()))and9. The lexical definition of 𝑞 is irrelevant to nearest-name lookup. In an authority-indexed model, write 𝖺𝗌𝗄@𝐻 for a request authorized to invoke the particular handler 𝐻, and abbreviate 𝑝𝖺𝗎𝗍𝗁:=𝗁𝖺𝗇𝖽𝗅𝖾𝐻𝗈𝗎𝗍(𝗅𝖾𝗍𝑞=𝜆().𝖺𝗌𝗄@𝐻𝗈𝗎𝗍()𝗂𝗇𝗁𝖺𝗇𝖽𝗅𝖾𝐻𝗂𝗇(𝑞())). Identity-matched dispatch instead skips the wrong-identity inner handler, so the initial program and its result are 𝑝𝖺𝗎𝗍𝗁and7. Both programs have the same effect presence information, namely that 𝖺𝗌𝗄 may occur. They differ in handler identity.
The distinction becomes sharper when the closure escapes. Give the outer handler a fresh runtime label ℓ𝗈𝗎𝗍, and let the returned closure retain the corresponding authority: 𝗅𝖾𝗍𝑞=𝗁𝖺𝗇𝖽𝗅𝖾𝐻𝗈𝗎𝗍(𝗋𝖾𝗍𝗎𝗋𝗇(𝜆().𝖺𝗌𝗄@ℓ𝗈𝗎𝗍()))𝗂𝗇𝑞(). Handler return removes the delimiter and beta reduction exposes an authority use with no matching active label. The initial program therefore evaluates to the displayed stuck term: 𝗅𝖾𝗍𝑞=𝗁𝖺𝗇𝖽𝗅𝖾𝐻𝗈𝗎𝗍(𝗋𝖾𝗍𝗎𝗋𝗇(𝜆().𝖺𝗌𝗄@ℓ𝗈𝗎𝗍()))𝗂𝗇𝑞()and𝖺𝗌𝗄@ℓ𝗈𝗎𝗍(). The final term is stuck because ℓ𝗈𝗎𝗍 is no longer active. A sound static system must either prevent this escape or retain enough latent scope information to reject the later call.
Finally, operation equality does not imply handler equality: 𝗈𝗉(𝐻𝗈𝗎𝗍)=𝖺𝗌𝗄=𝗈𝗉(𝐻𝗂𝗇),𝐻𝗈𝗎𝗍≠𝐻𝗂𝗇. An effect row can state {𝖺𝗌𝗄}, but that statement alone authorizes neither handler. An effect capability is an explicit token naming authority at the call site; lexical tunnelling resolves authority instead from the lexical identity of a request.
★★☆ Assume an active outer handler 𝐻𝗈𝗎𝗍 surrounds each of the following request-bearing phrases: 𝖺𝗌𝗄(),𝗁𝖺𝗇𝖽𝗅𝖾𝐻𝗂𝗇(𝖺𝗌𝗄()),𝗎𝗇𝖽𝖾𝗋𝖨𝗇𝗇𝖾𝗋(𝜆().𝖺𝗌𝗄()). For each phrase, distinguish three quantities: the effect of the request body, the residual effect of the whole displayed phrase before any surrounding outer handler is applied, and the residual effect of the complete outer-handled program. In particular, an inner handler discharges the whole phrase’s 𝖺𝗌𝗄 effect even though its request body has effect {𝖺𝗌𝗄}. Then state the handler selected by nearest-name lookup. Finally replace the request in each phrase by 𝖺𝗌𝗄@𝐻𝗈𝗎𝗍() and state the selected handler under explicit authority. Explain why a request effect alone cannot determine that identity.
The first repair makes authority explicit. The selected core is System 𝖷𝗂 from Effects as Capabilities[BSO20]. Its source syntax is fine-grain call by value: expressions are pure values, statements may control the continuation, and blocks are not expression values.
The source and runtime syntax are 𝜏::=𝖨𝗇𝗍∣𝖡𝗈𝗈𝗅∣1,𝜎::=(¯𝜏,¯𝜎)→𝜏,𝑒::=𝑥∣𝑣,𝑣::=()∣𝑛∣𝗍𝗋𝗎𝖾∣𝖿𝖺𝗅𝗌𝖾,𝑏::=𝑓∣𝑢,𝑢::=𝑤∣𝖼𝖺𝗉ℓ{(𝑥,𝑘)⇒𝑠},𝑤::={(¯𝑥:¯𝜏,¯𝑓:¯𝜎)⇒𝑠},𝑠::=𝗏𝖺𝗅𝑥=𝑠;𝑠∣𝑒∣𝖽𝖾𝖿𝑓=𝑏;𝑠∣𝑏(¯𝑒,¯𝑏)∣𝗁𝖺𝗇𝖽𝗅𝖾{𝐹⇒𝑠}𝗐𝗂𝗍𝗁{(𝑥,𝑘)⇒𝑠}∣#ℓ{𝑠}. Labels ℓ are fresh runtime names. Value contexts, block contexts, and label contexts are Γ::=∅∣Γ,𝑥:𝜏,Δ::=∅∣Δ,𝑓:𝜎,Ξ::=∅∣Ξ,ℓ:𝜏. Here 𝐹 is an operation name and 𝐻𝖷 is an evaluation context. Fix an operation signature Ω mapping each operation name 𝐹 to one block type 𝜏1→𝜏0, where 𝜏1→𝜏0 abbreviates the single-value, no-block-parameter type ((𝜏1),())→𝜏0. All System 𝖷𝗂 judgments below are relative to this fixed signature, which is suppressed from their notation. In particular, the parameter and result types of a handler are looked up rather than guessed. The expression fragment consists exactly of unit, integers, booleans, variables, and constants. The constant signature is C(())=1, C(𝑛)=𝖨𝗇𝗍, and C(𝗍𝗋𝗎𝖾)=C(𝖿𝖺𝗅𝗌𝖾)=𝖡𝗈𝗈𝗅. The label binding ℓ:𝜏 records the answer type of the delimiter. The label context is an ordered allocation stack: in Ξ0,ℓ:𝜏,Ξ+, the prefix Ξ0 existed when ℓ was allocated and the suffix Ξ+ contains only delimiters allocated later. Context lookup is rightmost. Ordinary source binders are alpha-renamed fresh; one handler form intentionally shadows: its handled premise binds a fresh capability for the operation name 𝐹, while its clause is typed in the unextended outer block context. Thus an outer capability named 𝐹 may remain available to the clause even though the handled body sees the newly bound one. The three typing judgments are Γ⊢𝑒:𝜏,Γ∣Δ∣Ξ⊢𝑏:𝜎,Γ∣Δ∣Ξ⊢𝑠:𝜏. Source terms have Ξ=∅; labels, delimiters, and capabilities appear only during evaluation. In the metatheory, runtime terms are indexed by their typing derivations, as in the source mechanization. The notation above erases those indices: a capability node retains the outer derivation of its handler body, and a delimiter node binds its fresh label in the derivation of its body. Consequently the runtime rules below classify generated configurations; they are not constructors with which one may forge an arbitrary capability and an unrelated body.
The complete source rules are the following. Expression rules are ordinary:
𝑥:𝜏∈Γ
Γ⊢𝑥:𝜏
X-Var
C(𝑣)=𝜏
Γ⊢𝑣:𝜏
X-Const
Blocks and statements use separate contexts:
Δ(𝑓)=𝜎
Γ∣Δ∣Ξ⊢𝑓:𝜎
X-BVar
Γ,¯𝑥:¯𝜏∣Δ,¯𝑓:¯𝜎∣Ξ⊢𝑠:𝜏
Γ∣Δ∣Ξ⊢{(¯𝑥:¯𝜏,¯𝑓:¯𝜎)⇒𝑠}:(¯𝜏,¯𝜎)→𝜏
X-Block
Γ⊢𝑒:𝜏
Γ∣Δ∣Ξ⊢𝑒:𝜏
X-Expr
Γ∣Δ∣Ξ⊢𝑠0:𝜏0Γ,𝑥:𝜏0∣Δ∣Ξ⊢𝑠1:𝜏1
Γ∣Δ∣Ξ⊢𝗏𝖺𝗅𝑥=𝑠0;𝑠1:𝜏1
X-Val
Γ∣Δ∣Ξ⊢𝑏:𝜎Γ∣Δ,𝑓:𝜎∣Ξ⊢𝑠:𝜏
Γ∣Δ∣Ξ⊢𝖽𝖾𝖿𝑓=𝑏;𝑠:𝜏
X-Def
Γ∣Δ∣Ξ⊢𝑏:(¯𝜏,¯𝜎)→𝜏0(Γ⊢𝑒𝑖:𝜏𝑖)𝑖(Γ∣Δ∣Ξ⊢𝑏𝑗:𝜎𝑗)𝑗
Γ∣Δ∣Ξ⊢𝑏(¯𝑒,¯𝑏):𝜏0
X-Call
Ω(𝐹)=𝜏1→𝜏0Γ∣Δ,𝐹:𝜏1→𝜏0∣Ξ⊢𝑠:𝜏Γ,𝑥:𝜏1∣Δ,𝑘:𝜏0→𝜏∣Ξ⊢𝑠ℎ:𝜏
Γ∣Δ∣Ξ⊢𝗁𝖺𝗇𝖽𝗅𝖾{𝐹⇒𝑠}𝗐𝗂𝗍𝗁{(𝑥,𝑘)⇒𝑠ℎ}:𝜏
X-Handle
The derivation-indexed runtime interface and label invariant are:
Ξ=Ξ0,ℓ:𝜏,Ξ+Γ,𝑥:𝜏1∣Δ,𝑘:𝜏0→𝜏∣Ξ0⊢𝑠ℎ:𝜏
Γ∣Δ∣Ξ⊢𝖼𝖺𝗉ℓ{(𝑥,𝑘)⇒𝑠ℎ}:𝜏1→𝜏0
X-Cap
ℓ∉dom(Ξ)Γ∣Δ∣Ξ,ℓ:𝜏⊢𝑠:𝜏
Γ∣Δ∣Ξ⊢#ℓ{𝑠}:𝜏
X-Delim
The decomposition in X-Cap records the capability’s allocation origin. Its stored body is typed in the birth prefix Ξ0, outside both its own delimiter and every later delimiter in Ξ+. The capability newly bound in the handled premise is therefore not in scope in its own clause; the only way to reenter that same delimiter is through continuation 𝑘, which reinstalls it. A same-spelled capability already present in the outer block context remains a distinct outer binding. Keeping the prefix, rather than merely deleting ℓ from an unordered set, is load bearing for preservation when a request crosses intervening delimiters. Rule X-BVar uses the rightmost lookup fixed above. Replacing it by unordered membership would admit the shadowed outer 𝐹 in the handled premise and would invalidate the translation argument below.
For example, assume 𝐵=𝖨𝗇𝗍→𝖨𝗇𝗍 and Ω(𝐹)=Δ(𝐹)=𝐵. Write 𝑠20=𝗁𝖺𝗇𝖽𝗅𝖾{𝐹⇒𝐹(20)}𝗐𝗂𝗍𝗁{(𝑥,𝑘)⇒𝑘(𝑥)}. Then Ω(𝐹)=𝐵(Δ,𝐹:𝐵)(𝐹)=𝐵Γ⊢20:𝖨𝗇𝗍Γ∣Δ,𝐹:𝐵∣∅⊢𝐹(20):𝖨𝗇𝗍X−Call(Δ,𝑘:𝐵)(𝑘)=𝐵Γ,𝑥:𝖨𝗇𝗍⊢𝑥:𝖨𝗇𝗍Γ,𝑥:𝖨𝗇𝗍∣Δ,𝑘:𝐵∣∅⊢𝑘(𝑥):𝖨𝗇𝗍X−CallΓ∣Δ∣∅⊢𝑠20:𝖨𝗇𝗍X−Handle. This derivation uses every source judgment: the arguments are expressions, 𝐹 and 𝑘 are blocks, and the whole program is a statement.
★☆☆ Assume Ω(𝐹)=Δ(𝐹)=1→𝖨𝗇𝗍. Derive the type of 𝗁𝖺𝗇𝖽𝗅𝖾{𝐹⇒𝗏𝖺𝗅𝑥=𝐹(());𝑥}𝗐𝗂𝗍𝗁{(𝑢,𝑘)⇒𝑘(7)}. State the type of the continuation block and the common answer type at all four positions of X-Handle.
The tempting escape term is 𝗁𝖺𝗇𝖽𝗅𝖾{𝐹⇒𝐹}𝗐𝗂𝗍𝗁{(𝑥,𝑘)⇒𝑘(𝑥)}. It has no typing derivation. The handled body must be a statement of a value type 𝜏, but 𝐹 is a block variable and there is no rule that embeds a block judgment into a statement or expression judgment. Likewise, value arguments cannot be blocks, and every block result is a value type. These are three faces of the same second-class restriction.
The restriction still permits higher-order blocks. A block may receive another block as an argument and invoke it while the defining delimiter is active: 𝖽𝖾𝖿𝗎𝗌𝖾={(𝑔:1→𝖨𝗇𝗍)⇒𝑔(())};𝗁𝖺𝗇𝖽𝗅𝖾{𝐹⇒𝖽𝖾𝖿𝑞={()⇒𝐹(())};𝗎𝗌𝖾(𝑞)}𝗐𝗂𝗍𝗁{(𝑢,𝑘)⇒𝑘(7)}. What is forbidden is returning 𝑞 as an expression value after the handler scope ends.
★☆☆ Assume 𝐹:1→𝖨𝗇𝗍 and 𝐺:(1,1→𝖨𝗇𝗍)→𝖨𝗇𝗍 in the block context. For each attempted System-𝖷𝗂 phrase below, identify the missing typing rule or violated syntactic category: 𝗏𝖺𝗅𝑥=𝐹;𝑥,{()⇒𝐹},𝐺(𝐹,𝐹). In the third phrase the first occurrence of 𝐹 occupies a value-argument position and the second occupies a block-argument position. Finish by deriving the well-typed call 𝐺((),𝐹), in which 𝐹 is used before its delimiter is removed.
Runtime labels are generated by handlers. General evaluation contexts and contexts delimited with respect to ℓ are 𝐻::=[]∣𝗏𝖺𝗅𝑥=𝐻;𝑠∣#ℓ{𝐻},𝐻ℓ::=[]∣𝗏𝖺𝗅𝑥=𝐻ℓ;𝑠∣#ℓ′{𝐻ℓ}(ℓ′≠ℓ). Thus 𝐻ℓ contains no delimiter labelled ℓ. The complete root contractions are 𝗏𝖺𝗅𝑥=𝑣;𝑠⇝0𝑠[𝑣/𝑥]𝑋−𝑉𝑎𝑙−𝑏𝑒𝑡𝑎,𝖽𝖾𝖿𝑓=𝑢;𝑠⇝0𝑠[𝑢/𝑓]𝑋−𝐷𝑒𝑓−𝑏𝑒𝑡𝑎,{(¯𝑥,¯𝑓)⇒𝑠}(¯𝑣,¯𝑢)⇝0𝑠[¯𝑣/¯𝑥][¯𝑢/¯𝑓]𝑋−𝐵𝑙𝑜𝑐𝑘−𝑏𝑒𝑡𝑎,#ℓ{𝑣}⇝0𝑣𝑋−𝐷𝑒𝑙𝑖𝑚−𝑟𝑒𝑡. Handler allocation is the fresh-label contraction 𝗁𝖺𝗇𝖽𝗅𝖾{𝐹⇒𝑠}𝗐𝗂𝗍𝗁{(𝑥,𝑘)⇒𝑠ℎ}⇝0#ℓ{𝑠[𝖼𝖺𝗉ℓ{(𝑥,𝑘)⇒𝑠ℎ}/𝐹]}𝑋−𝐻𝑎𝑛𝑑𝑙𝑒−𝑏𝑒𝑡𝑎. Capability capture substitutes both the request argument and a reified continuation: #ℓ{𝐻ℓ[𝖼𝖺𝗉ℓ{(𝑥,𝑘)⇒𝑠ℎ}(𝑣)]}⇝0𝑠ℎ[𝑣/𝑥,{(𝑦:𝜏0)⇒#ℓ{𝐻ℓ[𝑦]}}/𝑘]𝑋−𝐶𝑎𝑝−𝑏𝑒𝑡𝑎. The handler rule chooses ℓ fresh. Reduction ⟶ is compatible closure under 𝐻. A capability call is not a redex by itself; it reduces only together with the matching delimiter.
The earlier example calculates as follows: 𝗁𝖺𝗇𝖽𝗅𝖾{𝐹⇒𝗏𝖺𝗅𝑥=𝐹(20);𝑥}𝗐𝗂𝗍𝗁{(𝑥,𝑘)⇒𝑘(𝑥)}𝑋−𝐻𝑎𝑛𝑑𝑙𝑒−𝑏𝑒𝑡𝑎⇝0#ℓ{𝗏𝖺𝗅𝑥=𝖼𝖺𝗉ℓ{(𝑥,𝑘)⇒𝑘(𝑥)}(20);𝑥}𝑋−𝐶𝑎𝑝−𝑏𝑒𝑡𝑎⇝0{(𝑦:𝖨𝗇𝗍)⇒#ℓ{𝗏𝖺𝗅𝑥=𝑦;𝑥}}(20)𝑋−𝐵𝑙𝑜𝑐𝑘−𝑏𝑒𝑡𝑎⇝0#ℓ{𝗏𝖺𝗅𝑥=20;𝑥}𝑋−𝑉𝑎𝑙−𝑏𝑒𝑡𝑎⟶#ℓ{20}𝑋−𝐷𝑒𝑙𝑖𝑚−𝑟𝑒𝑡⇝020. The continuation reinstalls the delimiter, which is why the handler is deep.
The naive escaped capability 𝐻ℓ[𝖼𝖺𝗉ℓ{(𝑥,𝑘)⇒𝑠}(𝑣)] is stuck when there is no surrounding #ℓ. The label context is introduced precisely to prove that a closed source program cannot reduce to such a term.
A generated configuration is a runtime statement reachable from source syntax. Formally, write 𝖦𝖾𝗇Ω(𝑠) when there is a (possibly open) source statement 𝑠0, containing neither 𝖼𝖺𝗉ℓ nor #ℓ, such that 𝑠0⟶∗𝑠 under the fixed signature Ω. Thus “generated” is a reachability predicate, not an extra runtime constructor or an informal promise about provenance.
The safety proof needs the usual structural lemmas. They are stated for all three judgments simultaneously. A block substitution on a derivation is scope respecting when, at every X-Cap subderivation labelled ℓ, its restriction to the free block variables of the stored handler body is typable under the birth prefix Ξ0 displayed by that rule. Source substitutions are scope respecting because source blocks contain no labels. The substitutions created by the reduction rules are scope respecting because X-Handle-beta chooses ℓ fresh and the capability binding introduced for the handled occurrences of 𝐹 is absent from its own clause; any same-spelled 𝐹 in that clause denotes an outer binding. This is the derivation-indexed form of the second-class scope invariant.
If a generated System 𝖷𝗂 runtime judgment is derivable, then extending Γ or Δ by fresh bindings preserves it. Extending an ordered label context Ξ𝐿,Ξ𝑅 to Ξ𝐿,Ξ𝑠,Ξ𝑅, where the bindings of Ξ𝑠 are fresh, also preserves it. If the original derivation is scope respecting, the weakened derivation is scope respecting. Right-suffix weakening is the case Ξ𝑅=∅.
Proof. Induct on the derivation, retaining the cut Ξ𝐿|Ξ𝑅 at which Ξ𝑠 is inserted. Variable leaves use membership monotonicity, while block-variable leaves are unchanged because the insertion extends only Ξ, not Δ. Every ordinary rule applies the induction hypotheses to its premises. For X-Cap, compare the cut with the displayed decomposition Ξ0,ℓ:𝜏,Ξ+. If the cut lies in Ξ0, apply the induction hypothesis to the stored-body derivation; the enlarged prefix is the new birth prefix in the adjusted decomposition. If the cut lies at or to the right of ℓ, adjust only that decomposition and leave the stored body under its original prefix. Thus the capability-origin invariant is preserved. For X-Delim, alpha-rename its freshly bound ℓ away from Ξ𝑠, carry the same outer cut into its premise—that is, use the cut Ξ𝐿|(Ξ𝑅,ℓ:𝜏)—and reapply X-Delim. This proves arbitrary ordered insertion; iteration proves insertion of a finite fresh block. ◻
Let block types be nondependent. Adjacent distinct bindings in Δ may be exchanged. Moreover, if a judgment is derivable under Δ0,𝑓:𝜎,Δ1, appending a rightmost binding 𝑓:𝜎 preserves it; the new binding shadows the old one at the same type. Both transformations preserve scope respect.
Proof of Lemma 32.6 — Block-context exchange and identical shadowing
Proof. Induct on the derivation. For a block-variable leaf, rightmost lookup either selects a name different from the exchanged pair, selects one member with its unchanged type, or changes an old 𝑓:𝜎 lookup to the new 𝑓:𝜎 lookup. Every case has the same conclusion type. All other rules rebuild from their induction hypotheses. At X-Cap, perform the same transformation only on the block context; its recorded label birth prefix Ξ0 is unchanged, so the scope-respecting premise is preserved. ◻
The following hold for generated runtime derivations.
If Γ,𝑥:𝜏⊢𝑒:𝜏′ and Γ⊢𝑣:𝜏, then Γ⊢𝑒[𝑣/𝑥]:𝜏′.
If a block or statement is typed under Γ,𝑥:𝜏 and Γ⊢𝑣:𝜏, substituting 𝑣 for 𝑥 preserves its type.
If a block or statement is typed under Δ,𝑓:𝜎, and a scope-respecting substitution assigns a runtime block value 𝑢:𝜎 to 𝑓, applying that substitution preserves the judgment. At an ordinary occurrence of 𝑓, the value 𝑢 is typed under the current label context. At an occurrence stored below X-Cap with birth prefix Ξ0, the restricted substitution must type 𝑢 under Ξ0.
Proof of Lemma 32.7 — Value and scope-respecting block substitution
Proof. Induct on the typing derivation in each clause. The variable and block-variable cases split on whether the looked-up name is the substituted name. Binder cases alpha-rename bound names first. In X-Handle, apply value substitution to the operation parameter and block substitution to the continuation. In X-Cap, use the substitution restricted to the displayed birth prefix Ξ0; scope respect is exactly the premise needed for the stored handler-body derivation. In X-Delim, alpha-renaming keeps the fresh label outside the support of the substitution, so the freshness premise is unchanged. ◻
Proof. Invert the final typing rule. A variable conclusion is impossible in the corresponding empty variable context. The remaining expression rule produces a primitive value; the remaining block rules produce a block abstraction or a capability. In the capability case, inversion of X-Cap gives Ξ(ℓ)=𝜏′, hence ℓ∈dom(Ξ). ◻
If ∅∣∅∣Ξ⊢𝑠:𝜏, then at least one of the following operational alternatives is available:
𝑠 is an expression value;
there exists 𝑠′ with 𝑠⟶𝑠′; or
for some ℓ∈dom(Ξ), the statement has the undelimited form 𝑠=𝐻ℓ[𝖼𝖺𝗉ℓ{(𝑥,𝑘)⇒𝑠ℎ}(𝑣)].
The third alternative need not be unique when several outer labels are available; the statement asserts only that every irreducible nonvalue exposes one such authorized outer request.
Proof. Induct on the statement-typing derivation. An expression is a value by lemma 32.8. For sequencing, apply the induction hypothesis to the bound statement: a value gives X-Val-beta, a step lifts through the context, and an undelimited request remains undelimited after prefixing the sequencing context. A definition has a runtime block value by lemma 32.8 and contracts by X-Def-beta. For a closed block call, the operator and block arguments are runtime block values. A block abstraction gives X-Block-beta; item 1 of lemma 32.8 makes every ordinary value argument a primitive value, so no argument step is missing. A capability labelled ℓ gives the third alternative, and inversion of X-Cap puts ℓ in dom(Ξ). A handler gives X-Handle-beta.
For #ℓ{𝑠0}, apply the induction hypothesis to the premise typed under Ξ,ℓ:𝜏. A value gives X-Delim-ret, and a step lifts under the delimiter. If the induction hypothesis gives a request labelled ℓ, the outer delimiter and its no-ℓ-binding context form an X-Cap-beta redex. If the induction hypothesis gives a request labelled ℓ′≠ℓ, then prefixing #ℓ preserves the no-binding condition for ℓ′, so the whole statement has the third form for the outer label ℓ′∈dom(Ξ). ◻
Let a typing derivation of Γ∣Δ∣Ξ⊢𝐻[𝑠]:𝜏 contain a distinguished subderivation Γ′∣Δ′∣Ξ′⊢𝑠:𝜏0 at the unique hole of 𝐻. If Γ′∣Δ′∣Ξ′⊢𝑠′:𝜏0, then Γ∣Δ∣Ξ⊢𝐻[𝑠′]:𝜏. The same replacement property holds for a no-ℓ-binding context 𝐻ℓ, and replacement does not change its no-binding property.
Proof of Lemma 32.11 — Typed evaluation-context replacement
Proof. Induct on the context. For the empty context the replacement premise is the conclusion. A sequencing context uses the replacement induction hypothesis in the first premise of X-Val; its second premise is unchanged. A delimiter context uses the induction hypothesis in the premise of X-Delim; the fresh-label premise is unchanged. The grammar of 𝐻ℓ is the same induction with the additional fact that every crossed delimiter has label different from ℓ. ◻
For a generated, scope-respecting runtime derivation, if 𝖦𝖾𝗇Ω(𝑠),Γ∣Δ∣Ξ⊢𝑠:𝜏and𝑠⟶𝑠′, then Γ∣Δ∣Ξ⊢𝑠′:𝜏, and the reconstructed derivation of 𝑠′ is scope respecting.
For X-Handle-beta, write Ξ0 for the outer label context and choose fresh ℓ. Weakening types the handled computation under Ξ0,ℓ:𝜏. Its handler clause remains typed under its birth prefix Ξ0, so X-Cap, with empty later suffix, types the substituted capability at 𝜏1→𝜏0. The generated substitution is scope respecting: 𝐹 is bound only in the handled computation and is absent from its own handler clause. Block substitution types the handled body. Rule X-Delim then closes the fresh label scope.
For X-Cap-beta, write Ξ0 for the label context outside the matching delimiter. At the request occurrence, the crossed delimiters in 𝐻ℓ form a later suffix Ξ+. Inversion of X-Delim and X-Cap recovers the allocation decomposition Ξ0,ℓ:𝜏,Ξ+ and gives (Ξ0,ℓ:𝜏)(ℓ)=𝜏,Γ⊢𝑣:𝜏1,Γ,𝑥:𝜏1∣Δ,𝑘:𝜏0→𝜏∣Ξ0⊢𝑠ℎ:𝜏. By lemma 32.11, the typed no-binding context gives, for fresh 𝑦:𝜏0, Γ,𝑦:𝜏0∣Δ∣Ξ0⊢#ℓ{𝐻ℓ[𝑦]}:𝜏. Here lemma 32.5 first adds the fresh 𝑦:𝜏0 assumption to every inactive premise crossed while exposing the hole; context replacement then changes only the distinguished subderivation. Define the reified continuation 𝐾ℓ:={(𝑦:𝜏0)⇒#ℓ{𝐻ℓ[𝑦]}}. It has type 𝜏0→𝜏 under Ξ0. Simultaneous value and block substitution therefore types the reduct 𝑠ℎ[𝑣/𝑥,𝐾ℓ/𝑘] at 𝜏 in the outer context, exactly as required after the delimiter disappears. The no-ℓ-binding grammar for 𝐻ℓ contains no inner #ℓ, so the reinstalled delimiter is the unique matching binder. The suffix labels occur only inside the reified continuation; they are absent from the stored handler body, exactly as its birth-prefix premise requires. The delimiter-return case follows by inversion.
It remains to verify the second conclusion. Inspect the contracted root and then induct outward through its evaluation context. Ordinary beta roots introduce no capability. At X-Handle-beta, freshness of ℓ and separation of the handled premise from the clause give the stored body exactly its outer birth prefix. At X-Cap-beta, the no-ℓ-binding context reifies a continuation whose delimiter restores the same allocation point; the stored clause stays under its recorded prefix. Delimiter return removes a label and no stored body. Context replacement preserves these facts at each outer frame. ◻
No finite reduction prefix from a closed, well-typed source statement ends in a stuck statement containing an undelimited capability. Equivalently, every reachable nonvalue can step.
Proof. The closed source typing gives 𝖦𝖾𝗇Ω at the initial state. Apply lemma 32.4 and preservation at each step, then progress. Thus no reachable nonvalue is stuck on an undelimited System-𝖷𝗂 capability. ◻
★★☆ Consider rule X-Cap-beta. Reconstruct its preservation case using 𝐻ℓ=𝗏𝖺𝗅𝑧=[];𝑧. Give the reified continuation’s type and the label context in which the handler body is typed. Identify the premise that would fail if 𝐻ℓ contained an inner delimiter #ℓ. Also explain why a crossed #ℓ′, with ℓ′≠ℓ, lies in the later suffix rather than the handler body’s birth prefix.
Effekt replaces explicit System-𝖷𝗂 capability blocks and runtime labels by a source effect judgment. A closed set of operation names records the capabilities required from the context; the translation later restores one explicit capability parameter for each required name.
Let 𝜏::=𝖨𝗇𝗍∣𝖡𝗈𝗈𝗅∣1,𝜎::=(¯𝜏,¯𝜎)→𝜏/𝜀,𝜀::={𝐹1,…,𝐹𝑛},𝑣::=()∣𝑛∣𝗍𝗋𝗎𝖾∣𝖿𝖺𝗅𝗌𝖾,𝑒::=𝑥∣𝑣,𝑠::=𝗏𝖺𝗅𝑥=𝑠;𝑠∣𝑒∣𝖽𝖾𝖿𝑓(¯𝑥:¯𝜏,¯𝑔:¯𝜎):𝜏/𝜀=𝑠;𝑠∣𝑓(¯𝑒,¯𝑔)∣𝖾𝖿𝖿𝖾𝖼𝗍𝐹(𝑥:𝜏1):𝜏0;𝑠∣𝖽𝗈𝐹(𝑒)∣𝗍𝗋𝗒{𝑠}𝗐𝗂𝗍𝗁𝐹{(𝑥:𝜏1)⇒𝑠ℎ}. The contexts are a value context Γ, block context Δ, and operation signature Σ, where Σ(𝐹)=𝜏1→𝜏0. Value variables, ordinary block variables, and operation names are pairwise disjoint syntactic classes, and binders are alpha-renamed before extension. In cross-card comparisons these are Γ𝖤, Δ𝖤, and Σ𝖤; 𝐹 ranges over operation names, and no runtime-label context occurs in this source calculus. The judgments are Γ⊢𝑒:𝜏,Γ∣Δ∣Σ⊢𝑠:𝜏∣𝜀.
where 𝜀′0 is the inferred effect set of the body. The block closes over 𝜀′0∖𝜀0 at its definition site, and its declared type requires callers to provide every capability in 𝜀0. There is deliberately no premise requiring every member of 𝜀0 to occur in 𝜀′0: an unused annotated effect becomes an unused capability parameter, admitted by weakening. An implementation may warn about it, but must not reject it in this calculus.
For example, with Σ(𝖠𝗌𝗄)=1→𝖨𝗇𝗍, the block 𝖽𝖾𝖿𝑓():𝖨𝗇𝗍/{𝖠𝗌𝗄}=7;𝑓() is typable. Its body has inferred effect ∅, so 𝜀′0∖𝜀0=∅, while the call uses the declared set {𝖠𝗌𝗄}. Adding the tempting premise 𝜀0⊆𝜀′0 would reject this harmless unused capability and would invalidate effect weakening for block annotations.
The continuation is contextually pure: it is a second-class block whose own control effects are handled outside the operation clause.
Let 𝑠𝖺𝗌𝗄 abbreviate 𝗍𝗋𝗒{𝖽𝗈𝖠𝗌𝗄(())}𝗐𝗂𝗍𝗁𝖠𝗌𝗄{(𝑢:1)⇒𝗋𝖾𝗌𝗎𝗆𝖾(7)}. For the derivation only, abbreviate Σ𝐴:=Σ,𝖠𝗌𝗄:1→𝖨𝗇𝗍,Δ𝑟:=Δ,𝗋𝖾𝗌𝗎𝗆𝖾:𝖨𝗇𝗍→𝖨𝗇𝗍/∅. The complete source derivation is assembled from the request and resumption subderivations 𝖠𝗌𝗄:1→𝖨𝗇𝗍∈Σ𝐴Γ⊢():1Γ∣Δ∣Σ𝐴⊢𝖽𝗈𝖠𝗌𝗄(()):𝖨𝗇𝗍∣{𝖠𝗌𝗄}E−DoD𝖽𝗈 and Δ𝑟(𝗋𝖾𝗌𝗎𝗆𝖾)=𝖨𝗇𝗍→𝖨𝗇𝗍/∅Γ,𝑢:1⊢7:𝖨𝗇𝗍Γ,𝑢:1∣Δ𝑟∣Σ𝐴⊢𝗋𝖾𝗌𝗎𝗆𝖾(7):𝖨𝗇𝗍∣∅E−CallD𝗋𝖾𝗌𝗎𝗆𝖾. Using D𝖽𝗈 and D𝗋𝖾𝗌𝗎𝗆𝖾 as the two E-Try premises gives 𝖠𝗌𝗄:1→𝖨𝗇𝗍∈Σ𝐴D𝖽𝗈D𝗋𝖾𝗌𝗎𝗆𝖾Γ∣Δ∣Σ𝐴⊢𝑠𝖺𝗌𝗄:𝖨𝗇𝗍∣∅E−Try𝖠𝗌𝗄∉∅Γ∣Δ∣Σ⊢𝖾𝖿𝖿𝖾𝖼𝗍𝖠𝗌𝗄(𝑢:1):𝖨𝗇𝗍;𝑠𝖺𝗌𝗄:𝖨𝗇𝗍∣∅E−Effect. Rule E-Do introduces the requirement, E-Try removes it and types its resumption block, and E-Effect discharges the operation name from the signature context.
★☆☆ Write the nearest-name execution of the opening 𝗎𝗇𝖽𝖾𝗋𝖨𝗇𝗇𝖾𝗋(𝑞) example and identify the exact dynamic handler selected. Then rewrite the call in capability-passing style by adding one block parameter to 𝑞 and show which handler is selected.
Fix a canonical ordering of every effect set. Write 𝖢𝖺𝗉𝖳𝗒, 𝖢𝖺𝗉𝖤𝖿𝖿, and 𝖢𝖺𝗉𝖲𝗍𝗆𝗍Σ,Δ for the syntax translations; these are not semantic interpretations. Value types and expressions are unchanged. If Σ(𝐹)=𝜏1→𝜏0, put 𝖢𝖺𝗉𝖮𝗉Σ(𝐹):=𝜏1→𝜏0. For ¯𝐹=𝐹1,…,𝐹𝑛, let ―――――――𝖢𝖺𝗉𝖮𝗉Σ(¯𝐹):=𝖢𝖺𝗉𝖮𝗉Σ(𝐹1),…,𝖢𝖺𝗉𝖮𝗉Σ(𝐹𝑛). Then 𝖢𝖺𝗉𝖤𝖿𝖿Σ({¯𝐹}):=𝐹1:𝖢𝖺𝗉𝖮𝗉Σ(𝐹1),…,𝐹𝑛:𝖢𝖺𝗉𝖮𝗉Σ(𝐹𝑛),𝖢𝖺𝗉𝖳𝗒Σ((¯𝜏,¯𝜎)→𝜏0/{¯𝐹}):=(¯𝜏,𝖢𝖺𝗉𝖳𝗒Σ(¯𝜎),―――――――𝖢𝖺𝗉𝖮𝗉Σ(¯𝐹))→𝜏0. The statement translation is directed by the source typing derivation. Its subscript records the signature and the current source block context: the call clause reads the ordered effect list ¯𝐹 from Δ(𝑓), while a recursive call under a binder uses the extended current context. The fixed canonical ordering makes this context-directed translation deterministic. Its homomorphic clauses are 𝖢𝖺𝗉𝖲𝗍𝗆𝗍Σ,Δ(𝗏𝖺𝗅𝑥=𝑠0;𝑠1):=𝗏𝖺𝗅𝑥=𝖢𝖺𝗉𝖲𝗍𝗆𝗍Σ,Δ(𝑠0);𝖢𝖺𝗉𝖲𝗍𝗆𝗍Σ,Δ(𝑠1),𝖢𝖺𝗉𝖲𝗍𝗆𝗍Σ,Δ(𝑒):=𝑒,𝖢𝖺𝗉𝖲𝗍𝗆𝗍Σ,Δ(𝑓(¯𝑒,¯𝑔)):=𝑓(¯𝑒,¯𝑔,¯𝐹),𝖢𝖺𝗉𝖲𝗍𝗆𝗍Σ,Δ(𝖾𝖿𝖿𝖾𝖼𝗍𝐹(𝑥:𝜏1):𝜏0;𝑠):=𝖢𝖺𝗉𝖲𝗍𝗆𝗍Σ,Δ(𝑠),𝖢𝖺𝗉𝖲𝗍𝗆𝗍Σ,Δ(𝖽𝗈𝐹(𝑒)):=𝐹(𝑒). Block definitions receive the ordered capabilities explicitly: 𝖢𝖺𝗉𝖲𝗍𝗆𝗍Σ,Δ(𝖽𝖾𝖿𝑓(¯𝑥,¯𝑔):𝜏0/{¯𝐹}=𝑠0;𝑠):=𝖽𝖾𝖿𝑓={(¯𝑥,¯𝑔,¯𝐹)⇒𝖢𝖺𝗉𝖲𝗍𝗆𝗍Σ,Δ(𝑠0)};𝖢𝖺𝗉𝖲𝗍𝗆𝗍Σ,Δ(𝑠). Handlers bind the operation capability and resumption: 𝖢𝖺𝗉𝖲𝗍𝗆𝗍Σ,Δ(𝗍𝗋𝗒{𝑠}𝗐𝗂𝗍𝗁𝐹{(𝑥:𝜏1)⇒𝑠ℎ}):=𝗁𝖺𝗇𝖽𝗅𝖾{𝐹⇒𝖢𝖺𝗉𝖲𝗍𝗆𝗍Σ,Δ(𝑠)}:=𝗐𝗂𝗍𝗁{(𝑥,𝗋𝖾𝗌𝗎𝗆𝖾)⇒𝖢𝖺𝗉𝖲𝗍𝗆𝗍Σ,Δ(𝑠ℎ)}. The block-call clause uses the ordered effects in the declared type of 𝑓.
The complete handler example uses the earlier abbreviation 𝑠𝖺𝗌𝗄 and translates to 𝖢𝖺𝗉𝖲𝗍𝗆𝗍Σ,Δ(𝖾𝖿𝖿𝖾𝖼𝗍𝖠𝗌𝗄(𝑢:1):𝖨𝗇𝗍;𝑠𝖺𝗌𝗄)=𝗁𝖺𝗇𝖽𝗅𝖾{𝖠𝗌𝗄⇒𝖠𝗌𝗄(())}𝗐𝗂𝗍𝗁{(𝑢,𝗋𝖾𝗌𝗎𝗆𝖾)⇒𝗋𝖾𝗌𝗎𝗆𝖾(7)}. The operation declaration disappears, the request becomes an ordinary block call, and the handler explicitly binds the capability block. Set the System-𝖷𝗂 operation signature to Ω(𝗈𝗉)=Σ(𝗈𝗉) for every Effekt operation. Thus if Σ(𝗈𝗉)=𝐴→𝐵, the translated X-Handle premise uses parameter type 𝐴 and resumption-result type 𝐵, exactly as E-Try requires.
Proof of Theorem 32.15 — Effekt-to-System- Xi type preservation
Proof. Induct on the Effekt typing derivation. The expression and sequencing cases are homomorphic, using target weakening to place both translated premises under the union of their capability contexts.
For E-Def, write the annotated effects as 𝜀0 and the inferred body effects as 𝜀′0. The induction hypothesis types the translated body under 𝖢𝖺𝗉𝖳𝗒Σ(Δ,¯𝑔:¯𝜎),𝖢𝖺𝗉𝖤𝖿𝖿Σ(𝜀′0). Decompose the last context into the definition-site capabilities 𝖢𝖺𝗉𝖤𝖿𝖿Σ(𝜀′0∖𝜀0) and the formal capability parameters 𝖢𝖺𝗉𝖤𝖿𝖿Σ(𝜀0). Add a genuinely fresh formal by lemma 32.5; if its name already occurs at the same closed operation type, use identical shadowing from lemma 32.6. Exchange distinct adjacent bindings to restore the canonical order. Rule X-Block therefore gives exactly 𝖢𝖺𝗉𝖳𝗒Σ((¯𝜏,¯𝜎)→𝜏0/𝜀0). The continuation induction hypothesis is typed under 𝖢𝖺𝗉𝖤𝖿𝖿Σ(𝜀). Weakening both premises to 𝖢𝖺𝗉𝖤𝖿𝖿Σ((𝜀′0∖𝜀0)∪𝜀) and applying X-Def proves the case. In E-Call, the declared source block type fixes the same canonical order of capability arguments, so X-Call applies.
Translation erases E-Effect. Its side condition 𝐹∉𝜀 gives 𝖢𝖺𝗉𝖤𝖿𝖿Σ(𝜀∪{𝐹})=𝖢𝖺𝗉𝖤𝖿𝖿Σ(𝜀),𝐹:𝖢𝖺𝗉𝖳𝗒Σ(𝐹), so the premise already has the conclusion’s translated capability assumptions. Rule E-Do becomes X-Call on the capability block 𝐹. For E-Try, put Θ:=𝖢𝖺𝗉𝖳𝗒Σ(Δ),𝖢𝖺𝗉𝖤𝖿𝖿Σ((𝜀∖{𝐹})∪𝜀ℎ). The handled-statement induction hypothesis is typed under 𝖢𝖺𝗉𝖳𝗒Σ(Δ),𝖢𝖺𝗉𝖤𝖿𝖿Σ(𝜀). Since 𝖢𝖺𝗉𝖤𝖿𝖿Σ(𝜀∖{𝐹})⊆Θ, weakening adds the fresh capabilities in Θ. Exchange moves distinct bindings into canonical order. Append 𝐹:𝜏1→𝜏0 on the right; identical shadowing from lemma 32.6 preserves the derivation whether or not 𝜀ℎ already contributed an outer 𝐹, and rightmost lookup selects the handled binding. The handler-clause induction hypothesis is typed under 𝖢𝖺𝗉𝖳𝗒Σ(Δ),𝖢𝖺𝗉𝖤𝖿𝖿Σ(𝜀ℎ),𝗋𝖾𝗌𝗎𝗆𝖾:𝜏0→𝜏, and weakens to Θ,𝗋𝖾𝗌𝗎𝗆𝖾:𝜏0→𝜏. Rule X-Handle therefore yields the translated conclusion under exactly Θ. No translation clause creates a runtime label, so the target label context is empty. ◻
If ∅∣∅∣Σ⊢𝑠:𝜏∣∅, then every finite System-𝖷𝗂 execution prefix of 𝖢𝖺𝗉𝖲𝗍𝗆𝗍Σ,Δ(𝑠) ends in a value or a statement that can step. In particular, the translation cannot reach an unbound operation block or an undelimited escaped capability.
Proof. By theorem 32.15, the translation is closed and typed under an empty label context. Put Ω(𝗈𝗉)=Σ(𝗈𝗉). No clause of 𝖢𝖺𝗉𝖲𝗍𝗆𝗍Σ,Δ introduces 𝖼𝖺𝗉ℓ or #ℓ, so 𝑠0=𝖢𝖺𝗉𝖲𝗍𝗆𝗍Σ,Δ(𝑠) is the source witness in definition 32.2; the reflexive zero-step trace proves 𝖦𝖾𝗇Ω(𝑠0). Use lemma 32.4, theorem 32.12, theorem 32.10 at each execution step. This corollary belongs to the selected Effekt source language through its translation. It is not a theorem about every feature of the full Effekt implementation. ◻
★☆☆ Let 𝖽𝖾𝖿𝑞(𝑔:1→𝖨𝗇𝗍/{𝖠𝗌𝗄}):𝖨𝗇𝗍/{𝖫𝗈𝗀}=𝑠𝑞;𝑠 where 𝑞’s body calls 𝑔, 𝖠𝗌𝗄, and 𝖫𝗈𝗀. Write the translated System-𝖷𝗂 block type, block definition, and one call to 𝑞. Distinguish the capability passed to 𝑔 from the capability required by 𝑞 itself.
Capability passing forbids a capability from escaping by making blocks second class. Tunnelling takes another route: first-class functions may carry latent capability effects, and each request names the handler it intends to invoke. The calculus is independent of System 𝖷𝗂; no translation between them is assumed.
Write 𝜆𝗍𝗎𝗇 for the selected core of Abstraction-Safe Effect Handlers via Tunneling[ZM19a]. Its syntax is 𝑒::=𝛼∣ℓ∣ℎ.𝗅𝖻𝗅,𝑇,𝑆::=1∣𝖨𝗇𝗍∣𝑆→[𝑇]¯𝑒∣∀𝛼.𝑇∣Πℎ:𝖥.[𝑇]¯𝑒,ℎ,𝑔::=ℎ𝗏∣𝐻ℓ,𝐻,𝐺::=𝗁𝖺𝗇𝖽𝗅𝖾𝗋𝖥𝑥𝑘.𝑡,𝑡,𝑠::=()∣𝑛∣𝑥∣𝜆𝑥:𝑇.𝑡∣𝑡𝑠∣𝗅𝖾𝗍𝑥:𝑇=𝑡𝗂𝗇𝑠∣Λ𝛼.𝑡∣𝑡[¯𝑒]∣𝜆ℎ:𝖥.𝑡∣𝑡ℎ∣⇑ℎ∣⇓ℓ[𝑇]¯𝑒𝑡. Here ℎ𝗏 is an atomic handler variable and ℎ,𝑔 range over handler terms; binders use ℎ as a metavariable for such an atom. This repairs the self-referential ℎ::=ℎ∣𝐻ℓ printed in the source. The source core has only unit as a base type. The present card adds 𝖨𝗇𝗍, integer literals, their formation rules below, and no other construct; the running examples require a second observable base type. The form ⇑ℎ, read “request upward through handler ℎ,” invokes the authority carried by ℎ. The form ⇓ℓ[𝑇]¯𝑒𝑡, read “delimit downward at ℓ,” binds that handler label while 𝑡 runs. Within this separate calculus card, 𝑒 denotes a capability effect rather than a System 𝖷𝗂 expression, and 𝐻 denotes a handler body rather than a System 𝖷𝗂 evaluation context. Capability effects are effect variables, concrete labels, or the hidden label of a handler variable. Contexts are Δ::=∅∣Δ,𝛼,𝑃::=∅∣𝑃,ℎ:𝖥,Γ::=∅∣Γ,𝑥:𝑇,Ξ::=∅∣Ξ,ℓ:[𝑇]¯𝑒. Fix a global interface signature O with entries O(𝖥)=𝑇→𝑆, and write 𝗈𝗉(𝖥)=𝑇→𝑆 for that lookup. Here 𝑇→𝑆 abbreviates 𝑇→[𝑆]∅. An interface name is well formed exactly when it occurs in dom(O). Thus the four contexts are Δ𝖳, 𝑃𝖳, Γ𝖳, and Ξ𝖳 in cross-card comparisons; 𝖥 is an interface and 𝐻,𝐺 are handler values. Every context extension binds a fresh name unless a displayed substitution has first alpha-renamed the binder. In particular, Δ,𝛼, 𝑃,ℎ:𝖥, Γ,𝑥:𝑇, and Ξ,ℓ:[𝑇]¯𝑒 require the new name to be absent from the domain of the preceding context. The judgments are Δ∣𝑃∣Ξ⊢𝑇𝗍𝗒𝗉𝖾,Δ∣𝑃∣Ξ⊢¯𝑒𝖾𝖿𝖿𝖾𝖼𝗍𝗌,Δ∣𝑃∣Γ∣Ξ⊢𝑡:[𝑇]¯𝑒,Δ∣𝑃∣Γ∣Ξ⊢ℎ:𝖥∣𝑒. Effects are finite sequences modulo permutation, duplication, and flattening of substituted effect variables.
The selected signature makes its formation, ordinary typing, partial-order, and characteristic tunnelling rules explicit.
The well-formedness layer makes every effect constructor explicit:
Δ∣𝑃∣Ξ⊢∅𝖾𝖿𝖿𝖾𝖼𝗍𝗌
WF-Emp
𝛼∈Δ
Δ∣𝑃∣Ξ⊢𝛼𝖾𝖿𝖿𝖾𝖼𝗍𝗌
WF-EVar
ℓ∈dom(Ξ)
Δ∣𝑃∣Ξ⊢ℓ𝖾𝖿𝖿𝖾𝖼𝗍𝗌
WF-Label
𝑃(ℎ)=𝖥
Δ∣𝑃∣Ξ⊢ℎ.𝗅𝖻𝗅𝖾𝖿𝖿𝖾𝖼𝗍𝗌
WF-HLabel
Δ∣𝑃∣Ξ⊢¯𝑒1𝖾𝖿𝖿𝖾𝖼𝗍𝗌Δ∣𝑃∣Ξ⊢¯𝑒2𝖾𝖿𝖿𝖾𝖼𝗍𝗌
Δ∣𝑃∣Ξ⊢¯𝑒1,¯𝑒2𝖾𝖿𝖿𝖾𝖼𝗍𝗌
WF-ESeq
Δ∣𝑃∣Ξ⊢1𝗍𝗒𝗉𝖾
WF-Unit
Δ∣𝑃∣Ξ⊢𝖨𝗇𝗍𝗍𝗒𝗉𝖾
WF-Int
Δ∣𝑃∣Ξ⊢𝑆𝗍𝗒𝗉𝖾Δ∣𝑃∣Ξ⊢𝑇𝗍𝗒𝗉𝖾Δ∣𝑃∣Ξ⊢¯𝑒𝖾𝖿𝖿𝖾𝖼𝗍𝗌
Δ∣𝑃∣Ξ⊢𝑆→[𝑇]¯𝑒𝗍𝗒𝗉𝖾
WF-Fun
Δ,𝛼∣𝑃∣Ξ⊢𝑇𝗍𝗒𝗉𝖾
Δ∣𝑃∣Ξ⊢∀𝛼.𝑇𝗍𝗒𝗉𝖾
WF-EAll
Δ∣𝑃,ℎ:𝖥∣Ξ⊢𝑇𝗍𝗒𝗉𝖾Δ∣𝑃,ℎ:𝖥∣Ξ⊢¯𝑒𝖾𝖿𝖿𝖾𝖼𝗍𝗌
Δ∣𝑃∣Ξ⊢Πℎ:𝖥.[𝑇]¯𝑒𝗍𝗒𝗉𝖾
WF-HAll
For example, if 𝑃(ℎ)=𝖥, then WF-HLabel, WF-Unit, and WF-Fun derive Δ∣𝑃∣Ξ⊢1→[1]ℎ.𝗅𝖻𝗅𝗍𝗒𝗉𝖾.
The ordinary term rules are part of the selected local signature, not an implicit appeal to the simply typed lambda calculus:
Δ∣𝑃∣Γ∣Ξ⊢():[1]∅
T-Unit
Δ∣𝑃∣Γ∣Ξ⊢𝑛:[𝖨𝗇𝗍]∅
T-Int
𝑥:𝑇∈Γ
Δ∣𝑃∣Γ∣Ξ⊢𝑥:[𝑇]∅
T-Var
Δ∣𝑃∣Ξ⊢𝑆𝗍𝗒𝗉𝖾Δ∣𝑃∣Γ,𝑥:𝑆∣Ξ⊢𝑡:[𝑇]¯𝑒
Δ∣𝑃∣Γ∣Ξ⊢𝜆𝑥:𝑆.𝑡:[𝑆→[𝑇]¯𝑒]∅
T-Lam
Δ∣𝑃∣Γ∣Ξ⊢𝑡1:[𝑆→[𝑇]¯𝑒]¯𝑒Δ∣𝑃∣Γ∣Ξ⊢𝑡2:[𝑆]¯𝑒
Δ∣𝑃∣Γ∣Ξ⊢𝑡1𝑡2:[𝑇]¯𝑒
T-App
Δ∣𝑃∣Ξ⊢𝑆𝗍𝗒𝗉𝖾Δ∣𝑃∣Γ∣Ξ⊢𝑡1:[𝑆]¯𝑒Δ∣𝑃∣Γ,𝑥:𝑆∣Ξ⊢𝑡2:[𝑇]¯𝑒
Δ∣𝑃∣Γ∣Ξ⊢𝗅𝖾𝗍𝑥:𝑆=𝑡1𝗂𝗇𝑡2:[𝑇]¯𝑒
T-Let
Δ,𝛼∣𝑃∣Γ∣Ξ⊢𝑡:[𝑇]∅
Δ∣𝑃∣Γ∣Ξ⊢Λ𝛼.𝑡:[∀𝛼.𝑇]∅
T-EAbs
The compatibility family covers the displayed formation, ordinary typing, partial-order, and characteristic tunnelling rules. For T-Let, its compatibility case uses evaluation-context composition. Application and let use one common premise effect; the union-effect forms used later are derived by subsuming premises to a common join. Two preorders are part of the calculus. Type subtyping is the least transitive relation generated by
Δ∣𝑃∣Ξ⊢1≤1
S-Unit
Δ∣𝑃∣Ξ⊢𝖨𝗇𝗍≤𝖨𝗇𝗍
S-Int
Δ∣𝑃∣Ξ⊢𝑇2≤𝑇1Δ∣𝑃∣Ξ⊢𝑆1≤𝑆2Δ∣𝑃∣Ξ⊢¯𝑒1≤¯𝑒2
Δ∣𝑃∣Ξ⊢𝑇1→[𝑆1]¯𝑒1≤𝑇2→[𝑆2]¯𝑒2
S-Fun
Δ,𝛼∣𝑃∣Ξ⊢𝑇1≤𝑇2
Δ∣𝑃∣Ξ⊢∀𝛼.𝑇1≤∀𝛼.𝑇2
S-AllE
Δ∣𝑃,ℎ:𝖥∣Ξ⊢𝑇1≤𝑇2Δ∣𝑃,ℎ:𝖥∣Ξ⊢¯𝑒1≤¯𝑒2
Δ∣𝑃∣Ξ⊢Πℎ:𝖥.[𝑇1]¯𝑒1≤Πℎ:𝖥.[𝑇2]¯𝑒2
S-AllH
Δ∣𝑃∣Ξ⊢𝑇1≤𝑇2Δ∣𝑃∣Ξ⊢𝑇2≤𝑇3
Δ∣𝑃∣Ξ⊢𝑇1≤𝑇3
S-Trans
Effect inclusion is generated by (∀𝑗)(∃𝑖).𝑒1𝑗=𝑒2𝑖(Δ∣𝑃∣Ξ⊢𝑒2𝑖𝖾𝖿𝖿𝖾𝖼𝗍𝗌)𝑖Δ∣𝑃∣Ξ⊢¯𝑒1≤¯𝑒2Eff−Sub, where each 𝑒2𝑖 is read as a singleton effect sequence in the declared 𝖾𝖿𝖿𝖾𝖼𝗍𝗌 judgment. This formulation makes function domains contravariant, results and latent effects covariant, and both quantified forms pointwise. The term rule is Δ∣𝑃∣Γ∣Ξ⊢𝑡:[𝑇1]¯𝑒1Δ∣𝑃∣Ξ⊢𝑇1≤𝑇2Δ∣𝑃∣Ξ⊢¯𝑒1≤¯𝑒2Δ∣𝑃∣Γ∣Ξ⊢𝑡:[𝑇2]¯𝑒2T−Sub. The judgments are declarative: Eff-Sub compares normalized finite sets, type subtyping is the reflexive–transitive closure of its structural generators, and T-Sub may occur at any typing boundary. These rules alone do not define a principal-type algorithm or a unique placement of subsumption. When the finite effect preorder has the join ¯𝑒⋆=¯𝑒∪¯𝑒1∪¯𝑒2, subsume a function computation, its latent result effect, and its argument to ¯𝑒⋆, then apply T-App; the conclusion has effect ¯𝑒⋆. For sequencing, subsume both T-Let premises to ¯𝑒∪¯𝑒1∪¯𝑒2 derives sequencing at that union effect. Neither union-effect rule is primitive. The purity premise of T-EAbs is the selected source calculus’s explicit restriction on computations directly quantified by an effect variable; a body with an immediate nonempty effect cannot be hidden by effect abstraction.
Δ∣𝑃∣Γ∣Ξ⊢𝑡:[∀𝛼.𝑇]¯𝑒0Δ∣𝑃∣Ξ⊢¯𝑒𝖾𝖿𝖿𝖾𝖼𝗍𝗌
Δ∣𝑃∣Γ∣Ξ⊢𝑡[¯𝑒]:[𝑇[¯𝑒/𝛼]]¯𝑒0
T-EApp
Δ∣𝑃,ℎ:𝖥∣Γ∣Ξ⊢𝑡:[𝑇]¯𝑒
Δ∣𝑃∣Γ∣Ξ⊢𝜆ℎ:𝖥.𝑡:[Πℎ:𝖥.[𝑇]¯𝑒]∅
T-HAbs
Δ∣𝑃∣Γ∣Ξ⊢𝑡:[Πℎ:𝖥.[𝑇]¯𝑒]¯𝑒0Δ∣𝑃∣Γ∣Ξ⊢ℎ:𝖥∣𝑒
Δ∣𝑃∣Γ∣Ξ⊢𝑡ℎ:[𝑇[ℎ]]¯𝑒[ℎ],¯𝑒0
T-HApp
Here 𝑇[ℎ] and ¯𝑒[ℎ] replace the bound handler variable by its argument and replace ℎ.𝗅𝖻𝗅 by the argument label. The four characteristic handler and tunnelling rules are
The first side condition on T-Down states ℓ∉dom(Ξ). The two well-formedness premises are checked under Ξ, which does not contain ℓ; by WF-Label, they imply ℓ∉fl(𝑇,¯𝑒). This derived fact is the region-capability restriction: the fresh label may occur while the guarded term executes, but may not escape in the result type or residual effects.
For a complete use of both judgments, assume 𝑃(ℎ)=𝖥 and 𝗈𝗉(𝖥)=1→𝖨𝗇𝗍. Then Δ∣𝑃∣Ξ⊢1𝗍𝗒𝗉𝖾𝑃(ℎ)=𝖥Δ∣𝑃∣Γ,𝑥:1∣Ξ⊢ℎ:𝖥∣ℎ.𝗅𝖻𝗅T−HVar𝗈𝗉(𝖥)=1→𝖨𝗇𝗍Δ∣𝑃∣Γ,𝑥:1∣Ξ⊢⇑ℎ:[1→[𝖨𝗇𝗍]ℎ.𝗅𝖻𝗅]∅T−Up1→[𝖨𝗇𝗍]ℎ.𝗅𝖻𝗅≤1→[𝖨𝗇𝗍]ℎ.𝗅𝖻𝗅∅≤ℎ.𝗅𝖻𝗅Δ∣𝑃∣Γ,𝑥:1∣Ξ⊢⇑ℎ:[1→[𝖨𝗇𝗍]ℎ.𝗅𝖻𝗅]ℎ.𝗅𝖻𝗅T−Sub𝑥:1∈Γ,𝑥:1Δ∣𝑃∣Γ,𝑥:1∣Ξ⊢𝑥:[1]∅T−Var1≤1∅≤ℎ.𝗅𝖻𝗅Δ∣𝑃∣Γ,𝑥:1∣Ξ⊢𝑥:[1]ℎ.𝗅𝖻𝗅T−SubΔ∣𝑃∣Γ,𝑥:1∣Ξ⊢⇑ℎ𝑥:[𝖨𝗇𝗍]ℎ.𝗅𝖻𝗅T−AppΔ∣𝑃∣Γ∣Ξ⊢𝜆𝑥:1.⇑ℎ𝑥:[1→[𝖨𝗇𝗍]ℎ.𝗅𝖻𝗅]∅T−Lam. The handler judgment derives the effect ℎ.𝗅𝖻𝗅, the term judgment records it as a latent function effect, and the enclosing lambda itself is a value with no immediate effect.
A handler definition is paired with the label introduced by the surrounding ⇓. Substituting 𝐻ℓ for a handler variable ℎ also substitutes ℓ for ℎ.𝗅𝖻𝗅. Thus handler identity is lexical, not just an operation name.
★☆☆ Assume 𝑃(ℎ)=𝖥 and 𝗈𝗉(𝖥)=1→𝖨𝗇𝗍. Derive the type of 𝜆𝑥:1.⇑ℎ𝑥. Then show how the well-formedness premises of T-Down prevent ℓ from remaining in the function’s result effect annotation.
In the operational displays below, the result annotation [𝑇]¯𝑒 on a delimiter is suppressed when it is determined by the typing derivation. Values and evaluation contexts are 𝑣::=()∣𝜆𝑥:𝑇.𝑡∣Λ𝛼.𝑡∣𝜆ℎ:𝖥.𝑡∣⇑𝐻ℓ,𝐾::=[]∣𝐾𝑡∣𝑣𝐾∣𝐾[¯ℓ]∣𝐾𝐻ℓ∣𝗅𝖾𝗍𝑥:𝑇=𝐾𝗂𝗇𝑡∣⇓ℓ𝐾. Define the no-binding judgment ℓ⇝̸𝐾 by structural recursion on this grammar: ℓ⇝̸[],ℓ⇝̸𝐾𝑡,ℓ⇝̸𝑣𝐾,ℓ⇝̸𝐾[¯ℓ],ℓ⇝̸𝐾𝐻ℓ′ifℓ⇝̸𝐾,ℓ⇝̸𝗅𝖾𝗍𝑥:𝑇=𝐾𝗂𝗇𝑡ifℓ⇝̸𝐾,ℓ⇝̸⇓ℓ′𝐾ifℓ≠ℓ′andℓ⇝̸𝐾. These clauses are exhaustive: only the delimiter frame binds a runtime label. Reduction is compatible closure under 𝐾. Besides ordinary beta and let rules, the roots are (Λ𝛼.𝑡)[¯ℓ]⇝0𝑡[¯ℓ/𝛼],𝑇𝑢𝑛−𝐸𝑓𝑓−𝑏𝑒𝑡𝑎,(𝜆ℎ:𝖥.𝑡)𝐻ℓ⇝0𝑡[𝐻ℓ/ℎ],𝑇𝑢𝑛−𝐻𝑎𝑛𝑑𝑙𝑒𝑟−𝑏𝑒𝑡𝑎,⇓ℓ𝑣⇝0𝑣,𝑇𝑢𝑛−𝐷𝑜𝑤𝑛−𝑣𝑎𝑙,⇓ℓ𝐾[⇑𝐻ℓ𝑣]⇝0𝑡[𝑣/𝑥,(𝜆𝑦:𝑇2.⇓ℓ𝐾[𝑦])/𝑘],𝑇𝑢𝑛−𝐷𝑜𝑤𝑛−𝑢𝑝, where 𝐻=𝗁𝖺𝗇𝖽𝗅𝖾𝗋𝖥𝑥𝑘.𝑡, 𝗈𝗉(𝖥)=𝑇1→𝑇2, and the context 𝐾 does not bind ℓ. In particular, 𝐾 may contain ⇓ℓ′ for ℓ′≠ℓ.
Let 𝐻𝑜=𝗁𝖺𝗇𝖽𝗅𝖾𝗋𝖥𝑥𝑘.𝑘(7),𝐻𝑖=𝗁𝖺𝗇𝖽𝗅𝖾𝗋𝖥𝑥𝑘.𝑘(9), and abbreviate the two-request body by 𝐵(ℎ𝑜,ℎ𝑖):=𝗅𝖾𝗍𝑧:𝖨𝗇𝗍=⇑ℎ𝑖()𝗂𝗇⇑ℎ𝑜(). The tunneled program first invokes the inner handler and then uses the outer handler authority while the inner delimiter is still dynamically active: 𝑡𝗍𝗎𝗇:=⇓ℓ𝑜[𝖨𝗇𝗍]∅((𝜆ℎ𝑜:𝖥.⇓ℓ𝑖[𝖨𝗇𝗍]ℎ𝑜.𝗅𝖻𝗅((𝜆ℎ𝑖:𝖥.𝐵(ℎ𝑜,ℎ𝑖))𝐻ℓ𝑖𝑖))𝐻ℓ𝑜𝑜). Under ℎ𝑜:𝖥,ℎ𝑖:𝖥, the two requests have effects ℎ𝑖.𝗅𝖻𝗅 and ℎ𝑜.𝗅𝖻𝗅, respectively. Thus the let body has effects ℎ𝑖.𝗅𝖻𝗅,ℎ𝑜.𝗅𝖻𝗅. The inner handler application replaces ℎ𝑖.𝗅𝖻𝗅 by ℓ𝑖, and its delimiter discharges ℓ𝑖, leaving the still-abstract effect ℎ𝑜.𝗅𝖻𝗅. The outer T-HApp then replaces ℎ𝑜.𝗅𝖻𝗅 by ℓ𝑜, which the outer delimiter discharges. Hence ∅∣∅∣∅∣∅⊢𝑡𝗍𝗎𝗇:[𝖨𝗇𝗍]∅. Two handler-beta steps expose ⇓ℓ𝑜(⇓ℓ𝑖(𝗅𝖾𝗍𝑧:𝖨𝗇𝗍=⇑𝐻ℓ𝑖𝑖()𝗂𝗇⇑𝐻ℓ𝑜𝑜())). The inner request is handled first and resumes with 9. After the let binding is discharged, the remaining request is ⇑𝐻ℓ𝑜𝑜() inside the ℓ𝑖-delimiter. Since that delimiter binds ℓ𝑖, not ℓ𝑜, it belongs to the permitted context 𝐾 of Tun-Down-up. The outer request therefore crosses the intervening same-operation handler, reaches 𝐻ℓ𝑜𝑜, and returns 7. Nearest-name lookup on the same dynamic stack handles the second request at 𝐻ℓ𝑖𝑖 and returns 9. Tunnelling changes the matching key from the operation signature to lexical handler identity.
★★☆ After the two handler-beta steps for 𝑡𝗍𝗎𝗇, perform first the Tun-Down-up step at ℓ𝑖 and then the step at ℓ𝑜. Write both reified continuations explicitly. For the second step, explain why replacing ℓ𝑖≠ℓ𝑜 by ℓ𝑖=ℓ𝑜 violates the context side condition.
A naive logical relation would define the handler interpretation by structural recursion on the operation signature. Recursive signatures defeat that plan. Let 𝗈𝗉(𝖥)=1→Πℎ:𝖥.[𝑇]ℎ.𝗅𝖻𝗅,𝑅:=𝜆ℎ:𝖥.(⇑ℎ())ℎ, and let 𝐻:=𝗁𝖺𝗇𝖽𝗅𝖾𝗋𝖥𝑥𝑘.𝑘(𝑅). Then the closed term ⇓ℓ(𝑅𝐻ℓ) repeats: ⇓ℓ(𝑅𝐻ℓ)⟶⇓ℓ((⇑𝐻ℓ())𝐻ℓ)⟶(𝜆𝑦:Πℎ:𝖥.[𝑇]ℎ.𝗅𝖻𝗅.⇓ℓ(𝑦𝐻ℓ))𝑅⟶⇓ℓ(𝑅𝐻ℓ). The naive clause for H[[𝖥]] must interpret the handler-polymorphic result, whose V-clause asks for H[[𝖥]] again. The recursive call is not on a smaller type. The source repairs exactly this failed definition with a step-indexed logic and the later modality ▹. Recursive handler interpretations occur under one later; Löb induction allows ▹𝑃 as the hypothesis when proving 𝑃, and monotonicity removes one later from assumptions and conclusion together.
The source notation suppresses the numerical step index behind ▹. Its explicit syntactic parameter is the well-formed label environment Ξ=ℓ1:[𝑇1]¯𝑒1,…,ℓ𝑛:[𝑇𝑛]¯𝑒𝑛. There is no additional Kripke order of future label environments in this calculus. Rule T-Down temporarily extends Ξ by one fresh label; the later modality, not label-world extension, justifies recursive use of the step-indexed induction hypothesis at a smaller index.
The interpretation is parameterized by closing environments 𝛿::=∅∣𝛿,𝛼↦⟨¯ℓ1,¯ℓ2,𝜙⟩,𝜌::=∅∣𝜌,ℎ↦⟨𝐻ℓ11,𝐻ℓ22,𝜂⟩,𝛾::=∅∣𝛾,𝑥↦⟨𝑣1,𝑣2⟩. If 𝛿(𝛼)=⟨¯ℓ1,¯ℓ2,𝜙⟩, substitution replaces 𝛼 by ¯ℓ𝑖 on side 𝑖, and 𝜙 relates the two outcome families. If 𝜌(ℎ)=⟨𝐻ℓ11,𝐻ℓ22,𝜂⟩, the side-𝑖 closing environment maps ℎ to 𝐻ℓ𝑖𝑖, and 𝜂 relates the two handlers. Each binding 𝛾(𝑥)=⟨𝑣1,𝑣2⟩ consists of closed values satisfying the value relation at the type assigned to 𝑥. Every recursive occurrence of an effect signature lies under ▹, so unfolding it decreases the step index and the defining operator is contractive. All relations in the remainder of this definition are additionally indexed by this fixed syntactic Ξ. The index is suppressed in T,K,S,V,H,U,W, and the environment relations only to keep the formulas readable; it never denotes an implicit future-world order.
The observation relation is asymmetric termination approximation: O(𝑡1,𝑡2):=(∃𝑣1,𝑣2.𝑡1=𝑣1∧𝑡2⟶∗𝑣2)∨(∃𝑡′1.𝑡1⟶𝑡′1∧▹O(𝑡′1,𝑡2)). For closed terms, evaluation contexts, and potentially effect-stuck terms, define the biorthogonal relations T[[[𝑇]¯𝑒]]𝜌𝛿(𝑡1,𝑡2):=∀𝐾1,𝐾2.K[[[𝑇]¯𝑒]]𝜌𝛿(𝐾1,𝐾2)⇒O(𝐾1[𝑡1],𝐾2[𝑡2]),K[[[𝑇]¯𝑒]]𝜌𝛿(𝐾1,𝐾2):=(∀𝑣1,𝑣2.V[[𝑇]]𝜌𝛿(𝑣1,𝑣2)⇒O(𝐾1[𝑣1],𝐾2[𝑣2]))∧(∀𝑡1,𝑡2.S[[[𝑇]¯𝑒]]𝜌𝛿(𝑡1,𝑡2)⇒O(𝐾1[𝑡1],𝐾2[𝑡2])). The smaller relation S is not an informal exception to biorthogonality. It has the exact closure condition S[[[𝑇]¯𝑒]]𝜌𝛿(𝑢1,𝑢2):=∃𝐾1,𝐾2,𝑡1,𝑡2,𝜓,¯ℓ1,¯ℓ2.𝑢1=𝐾1[𝑡1]∧𝑢2=𝐾2[𝑡2]∧U[[¯𝑒]]𝜌𝛿(𝑡1,𝑡2,𝜓,¯ℓ1,¯ℓ2)∧(∀ℓ∈¯ℓ1.ℓ⇝̸𝐾1)∧(∀ℓ∈¯ℓ2.ℓ⇝̸𝐾2)∧∀𝑡′1,𝑡′2.𝜓(𝑡′1,𝑡′2)⇒▹T[[[𝑇]¯𝑒]]𝜌𝛿(𝐾1[𝑡′1],𝐾2[𝑡′2]). Thus a pair of isolated requests may be stuck, but every related outcome must become a related computation after plugging it back into contexts that do not bind the request labels.
The structural value relation is V[[1]]𝜌𝛿(𝑣1,𝑣2):=𝑣1=()∧𝑣2=(),V[[𝖨𝗇𝗍]]𝜌𝛿(𝑣1,𝑣2):=∃𝑛.𝑣1=𝑛∧𝑣2=𝑛,V[[𝑆→[𝑇]¯𝑒]]𝜌𝛿(𝑣1,𝑣2):=∀𝑢1,𝑢2.V[[𝑆]]𝜌𝛿(𝑢1,𝑢2)⇒T[[[𝑇]¯𝑒]]𝜌𝛿(𝑣1𝑢1,𝑣2𝑢2),V[[∀𝛼.𝑇]]𝜌𝛿(𝑣1,𝑣2):=∀¯ℓ1,¯ℓ2,𝜙.T[[[𝑇]∅]]𝜌𝛿[𝛼↦⟨¯ℓ1,¯ℓ2,𝜙⟩](𝑣1[¯ℓ1],𝑣2[¯ℓ2]),V[[Πℎ:𝖥.[𝑇]¯𝑒]]𝜌𝛿(𝑣1,𝑣2):=∀𝐻ℓ11,𝐻ℓ22,𝜂.▹H[[𝖥]](𝐻ℓ11,𝐻ℓ22,𝜂)⇒T[[[𝑇]¯𝑒]]𝜌[ℎ↦⟨𝐻ℓ11,𝐻ℓ22,𝜂⟩]𝛿(𝑣1𝐻ℓ11,𝑣2𝐻ℓ22). The handler relation unfolds one clause under related arguments and related continuations: H[[𝖥]](𝐻ℓ11,𝐻ℓ22,𝜂):=∃𝑡1,𝑡2,𝑇1,𝑇2.𝐻𝑖=𝗁𝖺𝗇𝖽𝗅𝖾𝗋𝖥𝑥𝑘.𝑡𝑖(𝑖=1,2)∧𝗈𝗉(𝖥)=𝑇1→𝑇2∧∀𝑣1,𝑣2.V[[𝑇1]]∅∅(𝑣1,𝑣2)⇒∀𝑢1,𝑢2.(∀𝑤1,𝑤2.V[[𝑇2]]∅∅(𝑤1,𝑤2)⇒𝜂(𝑢1𝑤1,𝑢2𝑤2))⇒𝜂(𝑡1[𝑣1/𝑥,𝑢1/𝑘],𝑡2[𝑣2/𝑥,𝑢2/𝑘]).
Finally, the semantic effect relation records both request forms and their outcomes. For an effect variable, U[[𝛼]]𝜌𝛿(𝑡1,𝑡2,𝜓,¯ℓ1,¯ℓ2):=∃¯ℓ′1,¯ℓ′2,𝜙.𝛿(𝛼)=⟨¯ℓ′1,¯ℓ′2,𝜙⟩∧𝜙(𝑡1,𝑡2,𝜓,¯ℓ1,¯ℓ2). The primed sequences are the syntactic substitutions carried by 𝛿; the semantic component 𝜙, rather than syntactic equality with those sequences, decides whether the currently exposed labels and outcomes are related. For a concrete capability effect 𝑒∈{ℓ,ℎ.𝗅𝖻𝗅}, let 𝜌𝑖(𝑒) replace handler-label projections on side 𝑖 and leave a concrete label unchanged. Then U[[𝑒]]𝜌𝛿(𝑡1,𝑡2,𝜓,¯ℓ1,¯ℓ2):=∃ℓ1,ℓ2.¯ℓ1=(ℓ1)∧¯ℓ2=(ℓ2)∧𝜌1(𝑒)=ℓ1∧𝜌2(𝑒)=ℓ2∧(U𝐴[[𝑒]]𝜌𝛿(𝑡1,𝑡2,𝜓,ℓ1,ℓ2)∨U𝐵[[𝑒]](𝑡1,𝑡2,𝜓,ℓ1,ℓ2)),U[[𝑒1,…,𝑒𝑛]]𝜌𝛿(𝑡1,𝑡2,𝜓,¯ℓ1,¯ℓ2):=∃𝑖.U[[𝑒𝑖]]𝜌𝛿(𝑡1,𝑡2,𝜓,¯ℓ1,¯ℓ2). The request clause is U𝐴[[𝑒]]𝜌𝛿(𝑡1,𝑡2,𝜓,ℓ1,ℓ2):=∃𝖥,𝑇,𝑇′,𝐻1,𝐻2,𝑣1,𝑣2.𝑡1=⇑𝐻ℓ11𝑣1∧𝑡2=⇑𝐻ℓ22𝑣2∧▹H[[𝖥]](𝐻ℓ11,𝐻ℓ22,W[[𝑒]]𝜌𝛿)∧𝗈𝗉(𝖥)=𝑇→𝑇′∧▹V[[𝑇]]∅∅(𝑣1,𝑣2)∧𝜓=▹V[[𝑇′]]∅∅. The context clause is deliberately asymmetric, matching the observation relation: U𝐵[[𝑒]](𝑡1,𝑡2,𝜓,ℓ1,ℓ2):=∃𝑡′1,𝑡′2.(∀𝐾.ℓ1⇝̸𝐾⇒⇓ℓ1𝐾[𝑡1]⟶+⇓ℓ1𝐾[𝑡′1])∧(∀𝐾.ℓ2⇝̸𝐾⇒⇓ℓ2𝐾[𝑡2]⟶∗⇓ℓ2𝐾[𝑡′2])∧𝜓={(𝑡′1,𝑡′2)}. Labels are interpreted by W[[ℎ.𝗅𝖻𝗅]]𝜌𝛿(𝑡1,𝑡2):=𝜌(ℎ)=⟨𝐻ℓ11,𝐻ℓ22,𝜂⟩∧𝜂(𝑡1,𝑡2),W[[ℓ]]𝜌𝛿(𝑡1,𝑡2):=∃𝑇,¯𝑒.Ξ(ℓ)=[𝑇]¯𝑒∧T[[[𝑇]¯𝑒]]𝜌𝛿(𝑡1,𝑡2).
Interpret the environments by EΔ(∅,𝛿):=𝛿=∅,EΔ(Δ,𝛼,𝛿):=∃𝛿′,¯ℓ1,¯ℓ2,𝜙.𝛿=𝛿′,𝛼↦⟨¯ℓ1,¯ℓ2,𝜙⟩∧EΔ(Δ,𝛿′),E𝑃(∅,𝜌):=𝜌=∅,E𝑃(𝑃,ℎ:𝖥,𝜌):=∃𝜌′,𝐻ℓ11,𝐻ℓ22,𝜂.𝜌=𝜌′,ℎ↦⟨𝐻ℓ11,𝐻ℓ22,𝜂⟩∧E𝑃(𝑃,𝜌′)∧H[[𝖥]](𝐻ℓ11,𝐻ℓ22,𝜂),E𝛿,𝜌Γ(∅,𝛾):=𝛾=∅,E𝛿,𝜌Γ(Γ,𝑥:𝑇,𝛾):=∃𝛾′,𝑣1,𝑣2.𝛾=𝛾′,𝑥↦⟨𝑣1,𝑣2⟩∧E𝛿,𝜌Γ(Γ,𝛾′)∧V[[𝑇]]𝜌𝛿(𝑣1,𝑣2). Open term refinement is the exact closing-substitution lifting Δ∣𝑃∣Γ∣Ξ⊧𝑡1⪯𝗅𝗈𝗀𝑡2:[𝑇]¯𝑒:=∀𝛿,𝜌,𝛾.EΔ(Δ,𝛿)∧E𝑃(𝑃,𝜌)∧E𝛿,𝜌Γ(Γ,𝛾)⇒T[[[𝑇]¯𝑒]]𝜌𝛿(𝛿1𝜌1𝛾1𝑡1,𝛿2𝜌2𝛾2𝑡2). Handler refinement is Δ∣𝑃∣Γ∣Ξ⊧ℎ1⪯𝗅𝗈𝗀ℎ2:𝖥∣𝑒:=∀𝛿,𝜌,𝛾.EΔ(Δ,𝛿)∧E𝑃(𝑃,𝜌)∧E𝛿,𝜌Γ(Γ,𝛾)⇒H[[𝖥]](𝛿1𝜌1𝛾1ℎ1,𝛿2𝜌2𝛾2ℎ2,W[[𝑒]]𝜌𝛿).
Proof. Choose one label ℓ∗ fresh for Ξ and for the finite supports of both closing environments. Alpha-rename the bound label of T-Down to ℓ∗before applying either closing substitution. Both closed instances therefore use the same concrete name. Extend the one suppressed syntactic index on both sides by the one open entry Ξ+:=Ξ,ℓ∗:[𝑇]¯𝑒; do not form separate entries from the two closed instances of 𝑇 and ¯𝑒. This common extension is required by the concrete-label clause W[[ℓ∗]], which performs one lookup in Ξ+.
Use the premise relation at Ξ+. Fresh-label index weakening embeds related test contexts 𝐾1,𝐾2 from Ξ into Ξ+. Bound labels in those contexts may be alpha-renamed away from ℓ∗, so ℓ∗⇝̸𝐾𝑖 for both 𝑖. If both guarded terms terminate normally, the premise relation supplies related values at 𝑇, and Tun-Down-val removes the two occurrences of the common delimiter. If a guarded term exposes ℓ∗, the two structural judgments above give the decomposition required by S. Its concrete-effect clause has ¯ℓ1=¯ℓ2=(ℓ∗); the U𝐵-clause contracts Tun-Down-up on both sides. The arguments use the request’s V-premise, and the reified continuations are 𝜆𝑦.⇓ℓ∗𝐾𝑖[𝑦]. The universally quantified outcome premise relates those continuations, and the leading ▹ lowers the numerical index before the recursive T-use.
The freshness discharge used in both alternatives is simultaneous strengthening of T,K,S,V,U, and W: if ℓ∗∉fl(𝑇,¯𝑒), restricting Ξ+ back to Ξ preserves the interpretation at [𝑇]¯𝑒. Prove it by induction on the displayed relation clauses and the numerical index. The only clause that inspects Ξ+ is W[[ℓ]]. The result side condition excludes a literal ℓ∗, and freshness for the supports of 𝛿 and 𝜌 excludes an effect-variable or handler-label instantiation to ℓ∗; every lookup is therefore unchanged. Thus the normal-return and exposed-request alternatives establish exactly the two clauses of O at the original index Ξ. ◻
Proof of Lemma 32.20 — Handler-definition compatibility
Proof. At numerical index 𝑛, define the candidate outcome relation 𝜂𝑛(𝑢1,𝑢2):=T[[[𝑆]¯𝑒]]𝜌𝛿(𝑢1,𝑢2)atindex𝑛. Assume as Löb hypothesis that the two handler values satisfy H[[𝖥]] at every smaller index. To establish its clause at 𝑛, take related operation arguments 𝑣1,𝑣2 and continuations 𝑢1,𝑢2 preserving 𝜂𝑛 on related results. Extend the closing substitution by 𝑥↦(𝑣1,𝑣2) and 𝑘↦(𝑢1,𝑢2). The clause-body induction hypothesis yields 𝜂𝑛(𝑡1[𝑣1/𝑥,𝑢1/𝑘],𝑡2[𝑣2/𝑥,𝑢2/𝑘]). Any recursive request through the handler consults W[[ℓ]]; its ▹H premise asks only for index 𝑛−1, exactly the Löb hypothesis. This proves the displayed H-clause and closes the induction on 𝑛. ◻
Every rule displayed in the tunnelling card preserves logical refinement; subappendix A.29 collects the same exact signature. The compatibility proof includes the evaluation-context case T-Let.
Proof. Proceed by induction on the typing derivation. Rule T-Unit uses the unit singleton clause, and T-Int uses the integer-equality clause; T-Var uses the related closing environment. Rule T-Sub uses type covariance and effect monotonicity: increasing the result type or effect weakens the observation required by the relation. Rule T-Lam uses the function clause of V.
For the first nontrivial biorthogonal case, consider T-App. After fixing related closing substitutions, write 𝑓𝑖 and 𝑢𝑖 for the two closed instances of its function and argument premises. Their induction hypotheses give T[[[𝑆→[𝑇]¯𝑒]¯𝑒]](𝑓1,𝑓2),T[[[𝑆]¯𝑒]](𝑢1,𝑢2). To prove the conclusion, fix 𝐾1,𝐾2∈K[[[𝑇]¯𝑒]]. If related function values 𝑔1,𝑔2 have already been obtained, the function clause of V says that 𝑔1𝑎1,𝑔2𝑎2 are T[[[𝑇]¯𝑒]]-related for every V[[𝑆]]-related pair 𝑎1,𝑎2. Hence the contexts 𝐾𝑖[𝑔𝑖[]] satisfy both clauses of K[[[𝑆]¯𝑒]]: the value clause uses the function relation, and the exposed-request clause is inherited by compatible closure. Applying the argument induction hypothesis gives O(𝐾1[𝑔1𝑢1],𝐾2[𝑔2𝑢2]). Therefore the outer contexts 𝐾𝑖[[]𝑢𝑖] satisfy both clauses of K[[[𝑆→[𝑇]¯𝑒]¯𝑒]]. Applying the function induction hypothesis yields O(𝐾1[𝑓1𝑢1],𝐾2[𝑓2𝑢2]), exactly the conclusion relation. This nested-context argument is the representative application pattern; it uses the common effect ¯𝑒 in both premises.
For T-Let, related 𝑡1 terms are placed in the evaluation context 𝗅𝖾𝗍𝑥:𝑆=[]𝗂𝗇𝑡2; the induction hypothesis for 𝑡2, under related substitutions extended at 𝑥, closes the context composition. Rules T-EAbs and T-EApp extend and instantiate 𝛿, while T-HAbs and T-HApp extend and instantiate 𝜌 using the quantified clauses of V. Rule T-HVar is immediate from E𝑃 and the W-clause for ℎ.𝗅𝖻𝗅.
For T-Up, related handlers and related arguments satisfy U𝐴, hence S; the inclusion S⊆T closes the case. Lemma 32.19 supplies the complete T-Down case, including both outcome alternatives and the fresh-label discharge. Lemma 32.20 supplies the T-HDef case with its explicit candidate 𝜂𝑛 and numerical Löb descent. These cases cover every rule in the selected local signature. ◻
A program context is generated by 𝐶::=[]∣𝐶[𝜆𝑥:𝑇.[]]∣𝐶[[]𝑡]∣𝐶[𝑡[]]∣𝐶[𝗅𝖾𝗍𝑥:𝑇=[]𝗂𝗇𝑡]∣𝐶[𝗅𝖾𝗍𝑥:𝑇=𝑡𝗂𝗇[]]∣𝐶[Λ𝛼.[]]∣𝐶[[][¯𝑒]]∣𝐶[𝜆ℎ:𝖥.[]]∣𝐶[[]ℎ]∣𝐶[𝑡(𝗁𝖺𝗇𝖽𝗅𝖾𝗋𝖥𝑥𝑘.[])ℓ]∣𝐶[(𝗁𝖺𝗇𝖽𝗅𝖾𝗋𝖥𝑥𝑘.[])ℓ]∣𝐶[⇓ℓ[𝑇]¯𝑒[]]. These are full program contexts, not the evaluation contexts 𝐾 used by the operational semantics. A well-formed closing context has judgment ⊢𝐶:Δ∣𝑃∣Γ∣Ξ∣[𝑇]¯𝑒⟹𝑇′. For well-typed terms at the displayed open boundary, write 𝖢𝗍𝗑𝖱𝖾𝖿(𝑡1,𝑡2) when, for every such closing program context and every result type 𝑇′, termination of 𝐶[𝑡1] implies termination of 𝐶[𝑡2].
Source import. This is Lemma 6 (Adequacy), §5.4, article p. 5:22 (physical p. 22) of [ZM19a]. The identity contexts form a related pair in K[[[𝑇]∅]]: their value clause is immediate, and their S-clause is vacuous because an empty effect sequence contains no effect that could witness an exposed related request. Unfolding T therefore gives the displayed observation. ◻
Proof of Corollary 32.24 — Tunnelling parametricity
Proof. Induction on the typing derivation applies lemma 32.21; the closing environments relate each bound variable to itself. The term and handler conclusions are the two displayed logical-refinement judgments. ◻
Source import. The two clauses map to Theorems 2–3, respectively, in §5.4, article p. 5:22 (physical p. 22) of [ZM19a]. The technical report states them in §5.4, pp. 21–22 and supplies the complete static signature and Compatibility Lemmas 7–19 in Appendix B [ZM19b].
Source Theorem 2 specializes the environments of corollary 32.24 to empty ones and the closed computation type [𝑇]∅. Its parametricity and lemma 32.23 give the stated value-or-step alternative for every reduct.
Source Theorem 3 assumes the same open typing boundary on both sides. Its adequacy and congruence hypotheses quantify over the full program contexts of definition 32.22, yielding contextual refinement at that boundary and at arbitrary observation result type.
The step-indexed, biorthogonal relation and its environment interpretation are source imports; the preceding local compatibility proof establishes only that the displayed rules meet their premises. No later result in this book uses a stronger consequence. ◻
★★☆ Assume 𝑃(ℎ)=𝖥 and 𝗈𝗉(𝖥)=1→1. Unfold the function clause of V for 1→[1]ℎ.𝗅𝖻𝗅. State the assumptions on the two unit arguments, then identify the U component used when the function bodies invoke ⇑ℎ. Explain where the handler environment 𝜌(ℎ) enters.
Effect presence does not bound resumption use. For the comparison predicate, write 𝗎𝗌𝖾𝗌(𝑟,𝑀)≤𝑞,𝑞∈{1,𝜔}, when every execution path of 𝑀 invokes resumption 𝑟 at most once for 𝑞=1, with no finite bound asserted for 𝑞=𝜔. A handler that resumes twice separates this predicate from effect safety: both resumptions may target an active handler even though the linear-use judgment rejects the clause. Tang, Hillerström, Lindley, and Morris develop the source calculus and qualified-effect discipline in Soundly Handling Linearity[THLM24]. The display above is only the book’s distinguishing predicate. No syntax, rule, or theorem of that calculus is imported into System 𝖷𝗂, Effekt, or 𝜆𝗍𝗎𝗇.
Bidirectional control: Olaf source card.
A unidirectional operation sends an argument to its handler and receives a resumption result. Olaf permits the handler computation itself to raise statically tracked effects back toward the suspended requester. Its source judgment and configuration step are Δ∣Θ∣Γ∣Ξ⊢𝑡:[𝜏]𝑐,𝐿;𝑡⟶𝐿′;𝑡′. Lifetimes occur in effect sequences, and a continuation type records effects on both sides of control transfer. These are Olaf objects: Θ is a lifetime-variable context here, 𝐿 is a lifetime store, and neither is the System-𝖷𝗂 translation abbreviation used above.
At the exact Olaf signature, well-typed terms are logically related to themselves; closed well-typed programs are value-or-step safe at every reduct; and logical refinement implies contextual refinement.
Source import. These are Theorems 1–3 in §6.2, article pp. 23–24 of [ZSM20]. Their hypotheses use Olaf’s worlds, fixpoint-handler relation, lifetime effects, and program contexts. They are not consequences of theorem 32.25, and they imply no translation between Olaf and System 𝖷𝗂, Effekt, or 𝜆𝗍𝗎𝗇. ◻
Locality: global-modality source card.
White’s locality calculus distinguishes ordinary bindings Γ;𝑥:𝜏 from global bindings Γ;𝑥:◻𝜏. Context restriction keeps only the latter: ∅/◻=∅,(Γ;𝑥:𝜏)/◻=Γ/◻,(Γ;𝑥:◻𝜏)/◻=(Γ/◻);𝑥:◻𝜏. The characteristic introduction premise is Γ/◻⊢𝖵𝑣:𝜏Γ⊢𝖵𝖻𝗈𝗑𝑣:◻𝜏Loc−Box. Thus a boxed value cannot retain an ordinary local binding. This is the source card of §3.2, Fig. 2, pp. 12–13 of [Whi26]; it is not System 𝖷𝗂’s second-class block restriction and supplies no theorem about its runtime labels.
Effect reflection: source card.
For an algebraic signature Σ, the source has a free-algebra type 𝑊Σ(𝜏) and a handler-mapping type 𝑦(Σ). Reflection and reification have the characteristic rules Γ⊢𝖵𝑣1:𝑦(Σ)𝗈𝗉:𝜏1⇝𝜏2∈ΣΓ⊢𝖵𝑣2:◻𝜏1Γ;𝑥:◻𝜏2⊢𝖢𝑐:𝜏3Γ⊢𝖢𝗋𝖾𝖿𝗅𝖾𝖼𝗍(𝑣1(𝗈𝗉))(𝑣2,𝑥.𝑐):𝜏3Refl−UpΓ;𝑥:𝑦(Σ)⊢𝖢𝑐:◻𝜏Γ⊢𝖢𝗋𝖾𝗂𝖿𝗒Σ(𝑥.𝑐):𝑊Σ(◻𝜏)Refl−Down. These are §3.4, Fig. 4, pp. 14–15 of [Whi26]. The semantic comparison in §4.8, p. 23 derives the reification isomorphism from Lemma 4.8 and Yoneda. Because this recent source is retained only as a source-gated comparison, the present block imports neither subject reduction nor normalization. In particular, reflection is not the authority-token discipline of System 𝖷𝗂 and is not the tunnelling request constructor.
Mechanism invariants and distinguishing tests
The distinctions can now be stated without relying on shared vocabulary. In this comparison only, an ownership capability is a permission whose typing tracks transfer or disposal of one resource; a capture set is the finite set of names a closure may mention; locality/effect reflection is a boundary discipline recording which effects are available inside, reflected outward, or confined; and control-flow linearity bounds the number of uses of a continuation or resumption. These are comparison predicates, not additional term formers or judgments of the three calculi developed above. A “region capability” in the exercise below means one member of a closure’s capture set that names a lexical region; no separate region calculus is assumed.
mechanism
static information
distinguishing test
Effect row
operation names that may occur
two same-named handlers satisfy the same row
Handler capability
authority for one runtime-labelled handler region
return a closure carrying the handler and test escape
Ownership capability
permission to access, transfer, or dispose of a resource
transfer a cell without installing any handler
Capture set
values or capabilities a closure may mention
closures with equal captures can call different handlers
Lexical handler identity
the particular handler variable or definition-label pair
nest two definitions of the same interface
Effect tunnelling
requests search for their named lexical handler through intervening frames
place an unrelated handler between request and owner
Locality/effect reflection
effects are available, reflected, or confined at a lexical boundary
return a capability across its lexical boundary
Control-flow linearity
how many times a continuation or resumption may be used
invoke one captured resumption twice
The first two columns state the static invariant; the third supplies a program shape that separates it from a neighboring invariant.
System 𝖷𝗂, Effekt, their translation, and source effect safety follow [BSO20]. The tunnelling calculus, logical relation, and fundamental, safety, and contextual-refinement theorems follow [ZM19a] and its technical report [ZM19b]. The final comparison cites Olaf’s bidirectional calculus [ZSM20].
★★☆ Reconstruct progress for the closed System-𝖷𝗂 statement 𝗁𝖺𝗇𝖽𝗅𝖾{𝐹⇒𝗏𝖺𝗅𝑥=𝐹(3);𝑥}𝗐𝗂𝗍𝗁{(𝑥,𝑘)⇒𝑘(𝑥)}. Give every intermediate runtime term, fresh-label premise, and typing judgment. Then replace the handled body by the illegal block escape 𝐹 and locate the first failed inversion.
★★★ Prove the E-Def and E-Try cases of theorem 32.15 in full detail, including the translated block contexts and the canonical ordering of effect arguments. Explain why the proof would not be syntax directed if different occurrences of the same effect set used different orders.
★★★ Rebuild the preceding compatibility proof for rule T-Down. State the freshness premise ℓ∉dom(Ξ), the extended label environment, the no-binding condition on evaluation contexts, the outcome relation after a matching request, and the point at which the derived fact ℓ∉fl(𝑇,¯𝑒) permits the fresh label binding to be discharged. Identify which two well-formedness premises imply that fact.
★★☆ Construct two well-typed programs that are both effect-safe but are observationally distinguishable because they choose different handlers for the same operation. Then construct two contextually equivalent pure terms whose compiled code could nevertheless be incorrect under a deliberately faulty compiler. State which overstrong implication each pair refutes.
★★☆ For each of the following requirements, choose effect rows, explicit capabilities, tunnelling, ownership, capture sets, or control-flow linearity, and justify the choice by a typing or operational invariant:
prevent a file token from being used after close;
ensure a request crosses an unrelated inner handler;
infer that a function may throw either of two exceptions;
guarantee a resumption is invoked at most once;
record that a closure mentions a region capability;
reject a capability call after its delimiter has returned, naming both the System-𝖷𝗂 second-class-block invariant and the tunnelling result-type/latent-effect non-escape invariant, and saying which calculus still admits a first-class closure;
For two items, explain why a plausible alternative is insufficient.
★★★Practical project.capability-model Implement the finite handler/capability model in appendix E. Distinguish operation names, handler identities, and runtime labels. Validate second-class escape and label scope. Translate one finite Effekt term to System 𝖷𝗂 while preserving its validated identities and labels, and implement a tunnel that searches by handler identity through an intervening handler for the same operation.
Maintain this invariant: every successful authorized request is handled by the unique handler whose identity and active label match its authority, after the finite model rejects duplicate handler identities and labels. The observable result is an exact ten-case report. The decidable acceptance test must cover authorized dispatch, accidental nearest-name capture, distinct same-operation identities, closure authority across a boundary, second-class escape rejection, invalid-label rejection, translation-label preservation, and tunneled dispatch, plus duplicate active-stack and duplicate source-binding rejection. Five typechecking mutations—name-only authority, nearest-handler tunnelling, omitted second-class rejection, omitted stack validation, and omitted translation validation—must each make the frozen oracle fail while the accepted source satisfies the gate in appendix E.