Prerequisites. Direct starred prerequisites: none. No later core chapter depends on this route.
The transaction from chapter 22 performs a write and may raise an exception. Treat 𝗍𝗋𝖺𝗇𝗌𝖺𝖼𝗍𝗂𝗈𝗇(𝑀) as a scoped operation: effects of 𝑀 commit on return and roll back on failure, while a computation sequenced after the transaction lies outside the rollback region. Put 𝑀:=𝗉𝗎𝗍(𝑠0+1)≫=𝜆_.𝗋𝖾𝗍𝗎𝗋𝗇(),𝑘:=𝜆_.𝗋𝖺𝗂𝗌𝖾(𝑒0). The first-order algebraicity equation from the previous chapter would force 𝗍𝗋𝖺𝗇𝗌𝖺𝖼𝗍𝗂𝗈𝗇(𝑀)≫=𝑘?=𝗍𝗋𝖺𝗇𝗌𝖺𝖼𝗍𝗂𝗈𝗇(𝑀≫=𝑘). The two sides do not have the same transactional boundary. On the left, 𝑀 returns, the write is committed, and only then does 𝑘 raise outside the transaction; the store visible with the failure is 𝑠0 +1. On the right, the same raise has been moved into the transaction body, so failure rolls the write back and exposes 𝑠0. Equation (23.1) has turned a continuation into part of the scope.
The running example makes the same defect visible without state. Let 𝗈𝗋 be nondeterministic choice and let 𝗈𝗇𝖼𝖾 select the first solution. With 𝑘(𝑥) =𝗈𝗋(𝑥,𝑥 +1), the intended calculation is 𝗈𝗇𝖼𝖾(𝗈𝗋(1,5))≫=𝑘𝑜𝑛𝑐𝑒=1≫=𝑘𝑙𝑒𝑓𝑡𝑢𝑛𝑖𝑡=𝗈𝗋(1,2). If 𝗈𝗇𝖼𝖾 were algebraic, bind would instead be pushed into its argument: 𝗈𝗇𝖼𝖾(𝗈𝗋(1,5))≫=𝑘false alg.=𝗈𝗇𝖼𝖾(𝗈𝗋(𝑘(1),𝑘(5)))definition of 𝑘=𝗈𝗇𝖼𝖾(𝗈𝗋(𝗈𝗋(1,2),𝗈𝗋(5,6)))𝑜𝑛𝑐𝑒=1. The problem is therefore structural, not a missing effect equation. An ordinary algebraic node stores parameters and response branches. A scoped node must additionally say which computation belongs to the scope and which computation follows it. The latter must remain outside when a later bind is performed.
We therefore freeze the syntax and construct its substitution directly.
★☆☆ Let 𝑀′:=𝗉𝗎𝗍(𝑠0+1)≫=𝜆_.𝗋𝖾𝗍𝗎𝗋𝗇7,𝑘′(𝑥):=𝗋𝖾𝗍𝗎𝗋𝗇(𝑥+1). Explain why the transactional contract does not distinguish the two programs 𝗍𝗋𝖺𝗇𝗌𝖺𝖼𝗍𝗂𝗈𝗇(𝑀′)≫=𝑘′and𝗍𝗋𝖺𝗇𝗌𝖺𝖼𝗍𝗂𝗈𝗇(𝑀′≫=𝑘′), and then identify the exact feature of 𝑘 in (23.1) that makes the original counterexample work. Why does agreement on this one successful continuation not restore algebraicity?
Referenced from 5 locations
The scoped signature
The source calculus separates ordinary algebraic operations from operations that own computations. A general functorial signature has a polynomial presentation that names the parameters and branches used in calculations.
A scoped signature is a pair (Σ,Γ) of endofunctors on 𝐒𝐞𝐭. The functor Σ describes ordinary algebraic operations and Γ describes scope creators.
For an elementwise presentation, fix sets O of ordinary operation symbols and S of scoped operation symbols, together with parameter and arity sets 𝑃𝑜, 𝑅𝑜(𝑜∈O),𝑃𝑠, 𝑄𝑠(𝑠∈S). The corresponding polynomial functors are Σ𝑋:=∐𝑜∈O𝑃𝑜×𝑋𝑅𝑜,Γ𝑋:=∐𝑠∈S𝑃𝑠×𝑋𝑄𝑠. Thus 𝑃𝑜 and 𝑃𝑠 are ordinary parameter sets. An ordinary operation has one continuation branch for each response in 𝑅𝑜. A scoped operation owns one scoped computation for each position in 𝑄𝑠.
Referenced from 6 locations
This polynomial presentation names parameters and branches for nondeterminism, exceptions, local state, and concurrency.
For 𝐻 :𝐒𝐞𝐭 →𝐒𝐞𝐭, put (G𝐻)𝐴:=𝐴+Σ(𝐻𝐴)+Γ(𝐻(𝐻𝐴)). Assume that the transfinite initial chain of this displayed endofunctor G has monic connecting maps and converges to an initial algebra. The scoped syntax endofunctor is the carrier 𝑇:=𝜇G. Consequently, for every set 𝐴, its constructors have the exact types 𝖵𝖺𝗋:𝐴→𝑇𝐴,𝖮𝗉:Σ(𝑇𝐴)→𝑇𝐴,𝖲𝖼𝗈𝗉𝖾:Γ(𝑇(𝑇𝐴))→𝑇𝐴. The functor action of 𝑇 is written 𝑇ℎ :𝑇𝐴 →𝑇𝐵 for ℎ :𝐴 →𝐵. Its constructor clauses are 𝑇ℎ(𝖵𝖺𝗋(𝑎))=𝖵𝖺𝗋(ℎ(𝑎)),𝑇ℎ(𝖮𝗉𝑜(𝑝,𝑘))=𝖮𝗉𝑜(𝑝,𝜆𝑟.𝑇ℎ(𝑘(𝑟))),𝑇ℎ(𝖲𝖼𝗈𝗉𝖾(𝑣))=𝖲𝖼𝗈𝗉𝖾(Γ(𝑇(𝑇ℎ))(𝑣)).
Referenced from 12 locations
The double occurrence 𝑇(𝑇𝐴) in the scope constructor is the essential one. A return from a computation inside a scope need not be a final 𝐴-value. It may instead be an entire 𝑇𝐴-computation representing what should happen after the scope closes. That extra layer is the explicit substitution: the inside return supplies the input to the continuation that follows the scope.
The nested shape is 𝖵𝖺𝗋 𝑎,𝖮𝗉(Σ(𝑇𝐴)),𝖲𝖼𝗈𝗉𝖾(Γ(𝑇(𝑇𝐴))).
The nondeterminism signature below has a monic initial chain that converges at 𝜔. The same conclusion holds for the exception signature when the exception set 𝐸 is finite, and for the local-state signature when the stored value set 𝑆 is finite. For arbitrary 𝐸 or 𝑆, this proposition makes no 𝜔-convergence claim; the transfinite hypothesis of definition 23.2 remains in force.
Referenced from 2 locations
Proof of Proposition 23.3 — Existence for the finitely branching running signatures
Proof. Under the stated hypotheses, every response and owned-position set displayed below is finite. Parameter sets may be arbitrary: they occur only as coefficients of sums and products. Hence Σ and Γ are finitary polynomial functors: they preserve injections and colimits of 𝜔-chains of injections. Starting from the empty endofunctor, induction on 𝑛 shows that every connecting map 𝑇𝑛 →𝑇𝑛+1 is componentwise injective; sums, finite products, finite powers, and the composite 𝑇𝑛(𝑇𝑛 −) preserve that property. At the limit, the nested summand uses the diagonal cofinality calculation colim𝑛𝑇𝑛(𝑇𝑛𝐴)≅colim(𝑚,𝑛)∈ℕ2𝑇𝑚(𝑇𝑛𝐴)≅(colim𝑚𝑇𝑚)((colim𝑛𝑇𝑛)𝐴). For the first isomorphism, every pair (𝑚,𝑛) maps to a diagonal stage (𝑁,𝑁) with 𝑁 ≥𝑚,𝑛; for the second, finitarity of each stage moves the inner colimit through 𝑇𝑚, after which the outer colimit is taken. Finitarity of Σ and Γ now gives G(colim𝑛𝑇𝑛) ≅colim𝑛G(𝑇𝑛), so 𝑇 =colim𝑛𝑇𝑛 is the initial algebra for the 𝗈𝗇𝖼𝖾, finite-exception, and finite-local-state signatures. ◻
Three running signatures
For nondeterminism with 𝖿𝖺𝗂𝗅, binary 𝗈𝗋, and unary 𝗈𝗇𝖼𝖾, take Σ𝑋≅1+𝑋×𝑋,Γ𝑋≅𝑋. The two summands of Σ are the nullary and binary algebraic nodes; 𝗈𝗇𝖼𝖾 owns one scoped computation.
For exceptions from a set 𝐸, the source gives Σ𝑋≅𝐸,Γ𝑋≅𝑋×𝑋𝐸. The ordinary operation is raise: an exception value is a parameter and there is no response branch. A scoped catch node owns one protected computation and one recovery computation for each exception. All those computations return the same intermediate result type; an outside continuation remains separate.
For local state with names 𝑁 and stored values 𝑆, take 𝑃𝗀𝖾𝗍=𝑁,𝑅𝗀𝖾𝗍=𝑆,𝑃𝗉𝗎𝗍=𝑁×𝑆,𝑅𝗉𝗎𝗍=1, so the ordinary signature and scoped part are Σ𝑋≅𝑁×𝑋𝑆+(𝑁×𝑆)×𝑋,Γ𝑋≅𝑁×𝑆×𝑋. A get node chooses one continuation branch from the stored value it receives; a put node carries a name and new value and has one unit-response branch. A local node has two ordinary parameters, a name and its initial value, and exactly one scoped computation. Its interpretation belongs to the source’s later semantic development and is not part of this syntax chapter.
★☆☆ Give polynomial data 𝑃𝑜,𝑅𝑜,𝑃𝑠,𝑄𝑠 realizing (23.7). Then state the types of the three corresponding elementwise constructors before any smart constructor notation is introduced.
Referenced from 3 locations
★☆☆ Rewrite (23.8) in polynomial form by taking the scoped-position set to be 1 +𝐸. Identify which position is the protected computation and which positions are recovery computations. What uniformity condition on their return type is forced by the single argument 𝑋 of Γ𝑋?
Referenced from 3 locations
The explicit substitution hidden in a scope node
The nested constructor is compact but conceals the three pieces that the opening calculation requires. Exposing them does not change the syntax.
Fix a polynomial scoped symbol 𝑠 ∈S. A scope node returning 𝐴 may be represented by data 𝑝:𝑃𝑠,𝑋:𝐒𝐞𝐭,𝑚:𝑄𝑠→𝑇𝑋,𝑘:𝑋→𝑇𝐴. We write this representative as 𝖲𝖼𝗈𝗉𝖾𝑠(𝑝;𝑋;𝑚;𝑘). The roles are distinct: componenttyperole𝑝𝑃𝑠ordinary parameters, fixed at the operation site𝑚𝑄𝑠→𝑇𝑋computations owned by the scope𝑘𝑋→𝑇𝐴continuation after the scope returns The intermediate set 𝑋 is not observable syntax. Replacing its names must not create a different node.
For ℎ :𝑋 →𝑌, 𝑚 :𝑄𝑠 →𝑇𝑋, and 𝑘′ :𝑌 →𝑇𝐴, a reindexing changes the intermediate carrier along ℎ while identifying 𝖲𝖼𝗈𝗉𝖾𝑠(𝑝;𝑋;𝑚;𝑘′∘ℎ)=𝖲𝖼𝗈𝗉𝖾𝑠(𝑝;𝑌;𝜆𝑞.𝑇ℎ(𝑚(𝑞));𝑘′). Equality of elementwise scoped nodes is the congruence generated by these reindexings and ordinary equality of their data. With 𝑠,𝑝,𝐴 fixed, denote the reindexing class of 𝖲𝖼𝗈𝗉𝖾𝑠(𝑝;𝑋;𝑚;𝑘) by [𝑋,𝑚,𝑘]. These square brackets form a quotient class; they are not the brackets in the explicit-substitution notation 𝑡[𝑓].
Referenced from 7 locations
Equation (23.12) says that an intermediate return can be renamed either before leaving the scope or in the explicit continuation. No handler or categorical representation theorem is being imported.
For fixed 𝑠,𝑝,𝐴, reindexing classes of representatives 𝖲𝖼𝗈𝗉𝖾𝑠(𝑝;𝑋;𝑚;𝑘) are in bijection with families 𝑢:𝑄𝑠→𝑇(𝑇𝐴). The maps are 𝗉𝖺𝖼𝗄[𝑋,𝑚,𝑘]:=𝜆𝑞.𝑇𝑘(𝑚(𝑞)),𝗎𝗇𝗉𝖺𝖼𝗄(𝑢):=[𝑇𝐴,𝑢,𝗂𝖽𝑇𝐴]. Under the polynomial identification (23.4), these are exactly the data in the 𝑠-summand of Γ(𝑇(𝑇𝐴)) from (23.6).
Referenced from 7 locations
Proof of Lemma 23.5 — Canonical nested representative
Proof. First check that 𝗉𝖺𝖼𝗄 respects one generating reindexing. The two representatives in (23.12) map at position 𝑞 to 𝑇(𝑘′∘ℎ)(𝑚(𝑞))functoriality of 𝑇=𝑇𝑘′(𝑇ℎ(𝑚(𝑞))). Hence 𝗉𝖺𝖼𝗄 is well defined on classes.
For 𝑢 :𝑄𝑠 →𝑇(𝑇𝐴), 𝗉𝖺𝖼𝗄(𝗎𝗇𝗉𝖺𝖼𝗄(𝑢))(𝑞)(23.13)=𝑇(𝗂𝖽𝑇𝐴)(𝑢(𝑞))functor identity=𝑢(𝑞). Conversely, instantiate (23.12) with ℎ =𝑘 :𝑋 →𝑇𝐴 and 𝑘′ =𝗂𝖽𝑇𝐴: [𝑋,𝑚,𝑘](23.12)=[𝑇𝐴,𝜆𝑞.𝑇𝑘(𝑚(𝑞)),𝗂𝖽𝑇𝐴](23.13)=𝗎𝗇𝗉𝖺𝖼𝗄(𝗉𝖺𝖼𝗄[𝑋,𝑚,𝑘]). Thus the maps are inverse. ◻
This lemma is the bridge between the readable representation (23.10) and the exact nested constructor.
Every stage functor preserves injections, so the least stage containing a representative is a well-founded rank. At a successor stage, unpack the scope and apply the rank hypotheses to its owned computations and continuation.
Under the monic and convergent initial-chain hypothesis of definition 23.2, every term for polynomial Σ and Γ has an elementwise representative in which every ordinary branch, every owned computation, and every continuation branch lies at an earlier stage of the initial construction of 𝑇. The least such stage is therefore a well-founded rank. Any elementwise definition whose recursive calls are restricted to those displayed components can be constructed by recursion on that rank, provided its scoped clause is invariant under reindexing.
Referenced from 4 locations
Proof of Lemma 23.6 — Well-founded elementwise recursion
Proof. Use the monic convergent transfinite initial chain of G fixed in definition 23.2. Its first stages are 𝑇0𝐴=0,𝑇𝛼+1𝐴=𝐴+Σ(𝑇𝛼𝐴)+Γ(𝑇𝛼(𝑇𝛼𝐴)), and a limit stage is the colimit of the preceding stages. The connecting maps are componentwise injective by hypothesis. A transfinite induction shows that every stage functor preserves injections. At a successor, this follows because sums and the polynomial functors Σ,Γ preserve injections and because the nested composite 𝑇𝛼(𝑇𝛼 −) does so when 𝑇𝛼 does. At a limit 𝜆, the stage is the pointwise colimit of the earlier chain. Suppose classes represented by 𝑥 ∈𝑇𝛼𝐴 and 𝑦 ∈𝑇𝛽𝐴 have equal images under an injection 𝑖 :𝐴 →𝐵. Equality in the chain colimit is witnessed at some 𝛾 <𝜆 above 𝛼 and 𝛽: the transported elements have equal images under 𝑇𝛾𝑖. Injectivity of 𝑇𝛾𝑖 makes the transported representatives equal, hence the original colimit classes are equal. Thus the limit stage also preserves injections. Since the connecting maps are monic, we may identify each stage with its image in the next one. At the convergence ordinal, the colimit is 𝑇 by the stated construction hypothesis.
Proceed by induction on the least stage containing the term. The same least-stage argument gives the following recursion schema. Given result sets 𝐷𝐴 and clauses 𝑐𝖵𝖺𝗋(𝑎):𝐷𝐴,𝑐𝖮𝗉(𝑝,𝑘,(𝐹(𝑘(𝑟)))𝑟):𝐷𝐴,𝑐𝖲𝖼𝗈𝗉𝖾(𝑝,𝑋,𝑚,𝑘,(𝐹(𝑚(𝑞)))𝑞,(𝐹(𝑘(𝑥)))𝑥):𝐷𝐴, with the scoped clause invariant under reindexing, define 𝐹𝐴(𝑡) at the least stage of 𝑡 by the corresponding clause. At a successor stage all displayed recursive arguments lie at an earlier stage; at a limit, the term already has a representative at an earlier stage. The connecting maps are injective, so a term cannot acquire a different constructor when transported to a later stage, and using the unique least stage makes the value independent of a later-stage presentation. Reindexing invariance makes it independent of the chosen elementwise representative. This constructs 𝐹; induction on least stage proves that it is the unique family satisfying the three clauses. ◻
Let P𝐴(𝑡) be a family of propositions that respects reindexing. To prove P𝐴(𝑡) for every set 𝐴 and every 𝑡 :𝑇𝐴, it suffices to prove variable:P𝐴(𝖵𝖺𝗋(𝑎));ordinary:(∀𝑟∈𝑅𝑜.P𝐴(𝑘(𝑟)))⟹P𝐴(𝖮𝗉𝑜(𝑝,𝑘));scoped:(∀𝑞∈𝑄𝑠.P𝑋(𝑚(𝑞)))∧(∀𝑥∈𝑋.P𝐴(𝑘(𝑥)))⟹P𝐴(𝖲𝖼𝗈𝗉𝖾𝑠(𝑝;𝑋;𝑚;𝑘)).
Referenced from 5 locations
Proof of Corollary 23.7 — Elementwise induction
Proof. Use the well-founded rank constructed in lemma 23.6.
Variables and ordinary nodes give the first two induction clauses directly. A scope introduced at stage 𝛼 +1 has, in the 𝑠-summand, parameters 𝑝 :𝑃𝑠 and a family 𝑢:𝑄𝑠→𝑇𝛼(𝑇𝛼𝐴). Take 𝑋:=𝑇𝛼𝐴, take 𝑚(𝑞) to be 𝑢(𝑞) followed by the stage inclusion into 𝑇𝑋, and take 𝑘 :𝑋 →𝑇𝐴 to be the stage inclusion. Then every 𝑚(𝑞) and every 𝑘(𝑥) comes from stage 𝛼, so the induction hypotheses give the premises of the scoped clause in (23.14). A term at a limit stage already appears at an earlier stage. Finally, because P respects (23.12), the conclusion is independent of the chosen elementwise representative. ◻
For 𝑡 :𝑇𝐴, the unary scoped operation has the elementwise form 𝗈𝗇𝖼𝖾(𝑡):=𝖲𝖼𝗈𝗉𝖾𝗈𝗇𝖼𝖾(∗;𝐴;𝜆_.𝑡;𝖵𝖺𝗋). Its canonical nested representative has body 𝑇𝖵𝖺𝗋(𝑡):𝑇(𝑇𝐴), so (23.15) is exactly the source program 𝖲𝖼𝗈𝗉𝖾(𝖮𝗇𝖼𝖾(𝖿𝗆𝖺𝗉 𝗋𝖾𝗍𝗎𝗋𝗇 𝑡)). The inserted 𝖵𝖺𝗋 is the explicit identity continuation.
Referenced from 4 locations
★★☆ Let 𝑄𝑠 ={𝐿,𝑅}, let 𝑋 ={0,1}, and let 𝑚(𝐿),𝑚(𝑅) :𝑇𝑋 and 𝑘 :𝑋 →𝑇𝐴 be arbitrary. Lemma 23.5 gives the representative [𝑋,𝑚,𝑘]; write its corresponding family in 𝑇(𝑇𝐴). Next suppose ℎ :𝑋 →𝑌 and 𝑘′ :𝑌 →𝑇𝐴 satisfy 𝑘 =𝑘′ ∘ℎ. Verify directly that [𝑋,𝑚,𝑘] and [𝑌,𝜆𝑞.𝑇ℎ(𝑚(𝑞)),𝑘′] pack to the same family in 𝑇(𝑇𝐴).
Referenced from 3 locations
The failed substitution and the hard repair
For an ordinary algebraic operation, substitution must recurse into every response branch. With elementwise notation, 𝖮𝗉𝑜(𝑝,𝑘),𝑘:𝑅𝑜→𝑇𝐴, so a substitution 𝑓 :𝐴 →𝑇𝐵 naturally sends 𝑘(𝑟) to 𝑘(𝑟)[𝑓]. From this point onward, 𝑡[𝑓] is postfix Kleisli substitution: its second argument is a map 𝑓 :𝐴 →𝑇𝐵. The notation deliberately resembles ordinary postfix substitution, but the displayed type distinguishes the two uses.
One tempting generic traversal copies that pattern into the owned computation while also preserving the explicitly stored continuation position: 𝖲𝖼𝗈𝗉𝖾𝑠(𝑝;𝑋;𝑚;𝑘)bad↦𝖲𝖼𝗈𝗉𝖾𝑠(𝑝;𝑋;𝜆𝑞.𝑚(𝑞)[𝑓];𝜆𝑥.𝑘(𝑥)[𝑓]). Call this the all-fields traversal. In general, (23.16) is not even typed. Applying the substitution to 𝑚(𝑞) :𝑇𝑋 first requires 𝑋 =𝐴. Even under that equality, the transformed body has type 𝑇𝐵, so the new scope carrier would have to be 𝐵, whereas the transformed old continuation is still indexed by 𝑥 :𝐴. Without a further adapter it has the required domain only when 𝐴 =𝐵. Thus the clause is typed in the endomorphic homogeneous special case 𝑋 =𝐴 =𝐵; there it duplicates the post-computation by moving it into the scope and retaining it after the scope. This is distinct from false algebraicity, which moves the post-computation into the scoped body and thereby loses it from the outside continuation. For the smart node 𝗈𝗇𝖼𝖾(𝑡) =𝖲𝖼𝗈𝗉𝖾𝗈𝗇𝖼𝖾( ∗;𝐴;𝜆_.𝑡;𝖵𝖺𝗋), the three results are correct:𝗈𝗇𝖼𝖾(𝑡;𝑓),false alg.:𝗈𝗇𝖼𝖾(𝑡[𝑓];𝖵𝖺𝗋),all-fields traversal:𝗈𝗇𝖼𝖾(𝑡[𝑓];𝑓). The opening calculation exhibits the second result; (23.16) specifies the third. A scoped computation and an outer continuation are different recursive positions.
For 𝑓 :𝐴 →𝑇𝐵, construct 𝑡[𝑓] :𝑇𝐵 by the least-stage recursion of lemma 23.6. On a stage-bounded elementwise representative, use the clauses 𝖵𝖺𝗋(𝑎)[𝑓]:=𝑓(𝑎),𝖮𝗉𝑜(𝑝,𝑘)[𝑓]:=𝖮𝗉𝑜(𝑝,𝜆𝑟.𝑘(𝑟)[𝑓]),𝖲𝖼𝗈𝗉𝖾𝑠(𝑝;𝑋;𝑚;𝑘)[𝑓]:=𝖲𝖼𝗈𝗉𝖾𝑠(𝑝;𝑋;𝑚;𝜆𝑥.𝑘(𝑥)[𝑓]). Every recursive call in (23.17) is then on an earlier-stage term; at a limit stage the term already comes from an earlier stage. This transfinite recursion constructs a candidate value from each elementwise representative.
Substitution descends through ordinary branches and through the explicit continuation of a scoped node. It leaves both the ordinary parameters 𝑝 and the scoped computations 𝑚 unchanged.
Referenced from 10 locations
The third line is the repair. It is also the reason explicit substitution was needed: the continuation is present as syntax and can be composed without pretending that it lies inside the scope.
Proof of Lemma 23.10 — Substitution respects reindexing
Proof. For any representative [𝑋,𝑚,𝑘], form the candidate 𝐶𝑓[𝑋,𝑚,𝑘]:=[𝑋,𝑚,𝜆𝑥.𝑘(𝑥)[𝑓]], where the substitutions in the continuation are already defined by the least-stage recursion. We show that 𝐶𝑓 is constant on each generating reindexing (23.12). Put 𝑘′𝑓(𝑦):=𝑘′(𝑦)[𝑓]. For the left representative, 𝐶𝑓[𝑋,𝑚,𝑘′∘ℎ]𝑐𝑎𝑛𝑑𝑖𝑑𝑎𝑡𝑒𝑑𝑒𝑓𝑖𝑛𝑖𝑡𝑖𝑜𝑛=[𝑋,𝑚,𝜆𝑥.𝑘′(ℎ(𝑥))[𝑓]]ℎ𝑒𝑙𝑝𝑒𝑟𝑑𝑒𝑓𝑖𝑛𝑖𝑡𝑖𝑜𝑛=[𝑋,𝑚,𝑘′𝑓∘ℎ]. For the right representative, 𝐶𝑓[𝑌,𝜆𝑞.𝑇ℎ(𝑚(𝑞)),𝑘′]definition=[𝑌,𝜆𝑞.𝑇ℎ(𝑚(𝑞)),𝑘′𝑓]. These two candidates are related by (23.12), now with continuation 𝑘′𝑓. Hence 𝐶𝑓 descends through the generated congruence. On every stage-bounded representative used in definition 23.9, the descended map is exactly the scoped recursive clause in (23.17). Therefore the recursively constructed substitution has the displayed value on every representative and is independent of the chosen representative. ◻
Consequently the candidate is independent of the chosen representative, so equation 23.17 defines substitution on every reindexing class.
The canonical nested clause follows rather than being guessed. Define 𝑏𝑓 :𝑇𝐴 →𝑇𝐵 by 𝑏𝑓(𝑢) =𝑢[𝑓]. A canonical representative [𝑇𝐴,𝑢,𝗂𝖽] becomes [𝑇𝐴,𝑢,𝑏𝑓] by (23.17). Canonicalizing it with lemma 23.5 gives 𝖲𝖼𝗈𝗉𝖾(𝑣)[𝑓]=𝖲𝖼𝗈𝗉𝖾(Γ(𝑇𝑏𝑓)(𝑣)). This is exactly the source implementation 𝖲𝖼𝗈𝗉𝖾𝑠𝑐≫=𝑓=𝖲𝖼𝗈𝗉𝖾(𝖿𝗆𝖺𝗉(𝖿𝗆𝖺𝗉(≫=𝑓))𝑠𝑐). The inner map traverses the scoped syntax only to reach its returned explicit continuations; it does not move 𝑓 underneath the scoped boundary as (23.16) does.
Ordinary and genuinely scoped calculations
For nondeterminism, define 𝖿𝖺𝗂𝗅:=𝖮𝗉𝖿𝖺𝗂𝗅(∗,𝖺𝖻𝗌𝗎𝗋𝖽0),𝗈𝗋(𝑡,𝑢):=𝖮𝗉𝗈𝗋(∗,𝜆𝑏.𝗂𝖿 𝑏 𝗍𝗁𝖾𝗇 𝑡 𝖾𝗅𝗌𝖾 𝑢). Then ordinary substitution is the familiar algebraic calculation: 𝗈𝗋(𝖵𝖺𝗋(1),𝖵𝖺𝗋(5))[𝑓](23.17)=𝗈𝗋(𝖵𝖺𝗋(1)[𝑓],𝖵𝖺𝗋(5)[𝑓])(23.17)=𝗈𝗋(𝑓(1),𝑓(5)).
Now make the continuation explicit in the unary scoped node: 𝗈𝗇𝖼𝖾(𝑡;𝑘):=𝖲𝖼𝗈𝗉𝖾𝗈𝗇𝖼𝖾(∗;𝑋;𝜆_.𝑡;𝑘),𝑡:𝑇𝑋,𝑘:𝑋→𝑇𝐴. The ordinary smart constructor is 𝗈𝗇𝖼𝖾(𝑡) =𝗈𝗇𝖼𝖾(𝑡;𝖵𝖺𝗋). Hence 𝗈𝗇𝖼𝖾(𝑡;𝑘)[𝑓](23.17)=𝗈𝗇𝖼𝖾(𝑡;𝜆𝑥.𝑘(𝑥)[𝑓]),𝗈𝗇𝖼𝖾(𝑡)[𝑓]identity continuation=𝗈𝗇𝖼𝖾(𝑡;𝑓). The body 𝑡 is byte-for-byte the same syntax in both lines. Only the explicit continuation changes.
For a concrete comparison, let 𝑡=𝗈𝗋(𝖵𝖺𝗋(1),𝖵𝖺𝗋(5)),𝑓(𝑥)=𝗈𝗋(𝖵𝖺𝗋(𝑥),𝖵𝖺𝗋(𝑥+1)). Then the three candidate clauses produce correct:𝗈𝗇𝖼𝖾(𝗈𝗋(𝖵𝖺𝗋(1),𝖵𝖺𝗋(5));𝑓),false algebraicity:𝗈𝗇𝖼𝖾(𝗈𝗋(𝗈𝗋(𝖵𝖺𝗋(1),𝖵𝖺𝗋(2)),𝗈𝗋(𝖵𝖺𝗋(5),𝖵𝖺𝗋(6)));𝖵𝖺𝗋),all-fields traversal:𝗈𝗇𝖼𝖾(𝗈𝗋(𝗈𝗋(𝖵𝖺𝗋(1),𝖵𝖺𝗋(2)),𝗈𝗋(𝖵𝖺𝗋(5),𝖵𝖺𝗋(6)));𝑓). The correct clause keeps the two original branches inside the scope and puts 𝑓 only in the outside continuation. False algebraicity moves 𝑓 into the owned computation and loses it outside. The all-fields traversal both moves and retains it, duplicating the post-computation.
Exceptions display both ordinary and scoped clauses. Define 𝗋𝖺𝗂𝗌𝖾(𝑒):=𝖮𝗉𝗋𝖺𝗂𝗌𝖾(𝑒,𝖺𝖻𝗌𝗎𝗋𝖽0),𝖼𝖺𝗍𝖼𝗁(𝑀,𝐻;𝑘):=𝖲𝖼𝗈𝗉𝖾𝖼𝖺𝗍𝖼𝗁(∗;𝑋;𝑚;𝑘), where 𝑀 :𝑇𝑋, 𝐻 :𝐸 →𝑇𝑋, and 𝑚(𝗂𝗇𝗅(∗))=𝑀,𝑚(𝗂𝗇𝗋(𝑒))=𝐻(𝑒). For 𝑓 :𝐴 →𝑇𝐵, the complete substitution calculations are 𝗋𝖺𝗂𝗌𝖾(𝑒)[𝑓](23.17)=𝗋𝖺𝗂𝗌𝖾(𝑒),𝖼𝖺𝗍𝖼𝗁(𝑀,𝐻;𝑘)[𝑓](23.17)=𝖼𝖺𝗍𝖼𝗁(𝑀,𝐻;𝜆𝑥.𝑘(𝑥)[𝑓]). The exception value 𝑒 is an ordinary parameter. The protected computation 𝑀 and every recovery computation 𝐻(𝑒) are owned by the catch scope. Only the continuation after catch is composed with 𝑓.
Local state makes all three roles visible at once. Write 𝗅𝗈𝖼𝖺𝗅(𝑛,𝑠,𝑡;𝑘):=𝖲𝖼𝗈𝗉𝖾𝗅𝗈𝖼𝖺𝗅((𝑛,𝑠);𝑋;𝜆_.𝑡;𝑘). Then 𝗅𝗈𝖼𝖺𝗅(𝑛,𝑠,𝑡;𝑘)[𝑓](23.17)=𝗅𝗈𝖼𝖺𝗅(𝑛,𝑠,𝑡;𝜆𝑥.𝑘(𝑥)[𝑓]). The name 𝑛 and initial state 𝑠 are ordinary parameters, the computation 𝑡 is owned by the local scope, and 𝑘 is the only component composed with the later substitution.
★☆☆ Let 𝑓(1) =𝗈𝗋(𝖵𝖺𝗋(10),𝖵𝖺𝗋(11)) and 𝑓(5) =𝖵𝖺𝗋(50). Expand (23.19) completely. How many 𝗈𝗋-nodes are in the resulting syntax tree, and which of them came from the original term?
Referenced from 3 locations
★★☆ Let 𝑡=𝗈𝗋(𝖵𝖺𝗋(1),𝖵𝖺𝗋(5)),𝑓(𝑥)=𝗈𝗋(𝖵𝖺𝗋(𝑥),𝖵𝖺𝗋(𝑥+1)). Calculate 𝗈𝗇𝖼𝖾(𝑡)[𝑓] using (23.20). Then write the ill-behaved endomorphic homogeneous results produced by false algebraicity and by the all-fields traversal (23.16). Identify exactly where the extra 𝗈𝗋-nodes occur and which candidate loses the outside continuation.
Referenced from 3 locations
★☆☆ For arbitrary 𝑡 :𝑇𝑋, 𝑘 :𝑋 →𝑇𝐴, and 𝑓 :𝐴 →𝑇𝐵, expand 𝗅𝗈𝖼𝖺𝗅(𝑛,𝑠,𝑡;𝑘)[𝑓]. Give one syntactic equality which would fail if substitution accidentally changed an ordinary parameter and one which would fail if it descended into 𝑡.
Referenced from 3 locations
Substitution equations and the monad
The construction is useful only if repeated explicit substitutions compose as ordinary substitution should. We prove this directly on the elementwise signature; no semantic interpretation is involved.
Assume Σ and Γ have the polynomial presentation (23.4). Let 𝑡 :𝑇𝐴, 𝑓 :𝐴 →𝑇𝐵, and 𝑔 :𝐵 →𝑇𝐶. Put 𝜂𝐴(𝑎) =𝖵𝖺𝗋(𝑎) and ℎ(𝑎):=𝑓(𝑎)[𝑔]. Then 𝖵𝖺𝗋(𝑎)[𝑓]=𝑓(𝑎),𝑡[𝜂𝐴]=𝑡,𝑡[𝑓][𝑔]=𝑡[ℎ]. All equalities are equality in the reindexing quotient of definition 23.4.
Referenced from 9 locations
Proof of Theorem 23.11 — Explicit-substitution equations
Proof. Equation (23.22a) is the first defining clause of definition 23.9. For (23.22b), apply corollary 23.7 to the family P𝑍(𝑢)⟺𝑢[𝜂𝑍]=𝑢. For (23.22c), define Q𝑍(𝑢)⟺∀𝐵,𝐶,𝑓:𝑍→𝑇𝐵,𝑔:𝐵→𝑇𝐶.(𝑢[𝑓])[𝑔]=𝑢[(𝜆𝑧.𝑓(𝑧)[𝑔])]. Both families respect reindexing because substitution is well defined by lemma 23.10. The variable case of P is 𝖵𝖺𝗋(𝑧)[𝜂𝑍]=𝜂𝑍(𝑧)=𝖵𝖺𝗋(𝑧) by the variable clause and the definition of 𝜂𝑍. At an ordinary node, function extensionality and the induction hypotheses on every response branch give 𝖮𝗉𝑜(𝑝,𝑘)[𝜂𝐴](23.17)=𝖮𝗉𝑜(𝑝,𝜆𝑟.𝑘(𝑟)[𝜂𝐴])𝐼𝐻=𝖮𝗉𝑜(𝑝,𝑘). At a scoped node, the scoped computations are not traversed: 𝖲𝖼𝗈𝗉𝖾𝑠(𝑝;𝑋;𝑚;𝑘)[𝜂𝐴](23.17)=𝖲𝖼𝗈𝗉𝖾𝑠(𝑝;𝑋;𝑚;𝜆𝑥.𝑘(𝑥)[𝜂𝐴])𝐼𝐻=𝖲𝖼𝗈𝗉𝖾𝑠(𝑝;𝑋;𝑚;𝑘). This proves (23.22b).
For (23.22c), apply the induction just described to Q, and then instantiate its universal quantifiers with the displayed 𝐵,𝐶,𝑓,𝑔. The variable case is 𝖵𝖺𝗋(𝑎)[𝑓][𝑔] =𝑓(𝑎)[𝑔] =ℎ(𝑎) =𝖵𝖺𝗋(𝑎)[ℎ] by the variable clause. The ordinary case is 𝖮𝗉𝑜(𝑝,𝑘)[𝑓][𝑔](23.17)=𝖮𝗉𝑜(𝑝,𝜆𝑟.𝑘(𝑟)[𝑓][𝑔])𝐼𝐻=𝖮𝗉𝑜(𝑝,𝜆𝑟.𝑘(𝑟)[ℎ])(23.17)=𝖮𝗉𝑜(𝑝,𝑘)[ℎ]. The scoped case is the load-bearing one: 𝖲𝖼𝗈𝗉𝖾𝑠(𝑝;𝑋;𝑚;𝑘)[𝑓][𝑔](23.17)=𝖲𝖼𝗈𝗉𝖾𝑠(𝑝;𝑋;𝑚;𝜆𝑥.𝑘(𝑥)[𝑓][𝑔])𝐼𝐻=𝖲𝖼𝗈𝗉𝖾𝑠(𝑝;𝑋;𝑚;𝜆𝑥.𝑘(𝑥)[ℎ])(23.17)=𝖲𝖼𝗈𝗉𝖾𝑠(𝑝;𝑋;𝑚;𝑘)[ℎ]. The body 𝑚 is unchanged on all four lines. By lemma 23.10, the calculation descends from representatives to reindexing classes. ◻
Under the polynomial hypothesis of theorem 23.11, define 𝗋𝖾𝗍𝗎𝗋𝗇𝑎:=𝖵𝖺𝗋(𝑎),𝑡≫=𝑓:=𝑡[𝑓]. Then 𝑇 satisfies the three monad laws: 𝗋𝖾𝗍𝗎𝗋𝗇𝑎≫=𝑓=𝑓(𝑎),𝑡≫=𝗋𝖾𝗍𝗎𝗋𝗇=𝑡,(𝑡≫=𝑓)≫=𝑔=𝑡≫=(𝜆𝑎.𝑓(𝑎)≫=𝑔).
Referenced from 5 locations
Proof of Corollary 23.12 — Scoped-syntax monad
Proof. Left and right unit are (23.22a) and (23.22b). Associativity is (23.22c). In each case, expand (23.23). ◻
The functorial renaming already present in the exact nested construction is not a second, unrelated traversal.
Under the same polynomial hypothesis, for 𝑟 :𝐴 →𝐵 and 𝑡 :𝑇𝐴, 𝑇𝑟(𝑡)=𝑡[𝖵𝖺𝗋∘𝑟].
Referenced from 2 locations
Proof of Lemma 23.13 — Renaming is return substitution
Proof. For each set 𝑍, let R𝑍(𝑢) assert (23.25) for every set 𝑊 and every map 𝑟 :𝑍 →𝑊. This family respects reindexing because both the functor action and substitution are well defined on the quotient. Apply corollary 23.7 to R and then instantiate it with the displayed 𝑟 :𝐴 →𝐵. The variable case is 𝑇𝑟(𝖵𝖺𝗋(𝑎))=𝖵𝖺𝗋(𝑟(𝑎))=𝖵𝖺𝗋(𝑎)[𝖵𝖺𝗋∘𝑟], by the functor and variable-substitution clauses. At an ordinary node, both sides preserve the parameter and apply the respective action pointwise to every response branch, so function extensionality applied to the induction hypotheses equates the resulting branch functions.
For a scoped representative [𝑋,𝑚,𝑘], first compute the source functor action through its canonical nested representative. Packing gives the body 𝑞 ↦𝑇𝑘(𝑚(𝑞)). Applying 𝑇𝑟 to the outer result applies 𝑇(𝑇𝑟) to that body, hence 𝑇(𝑇𝑟)(𝑇𝑘(𝑚(𝑞)))functoriality of 𝑇=𝑇((𝑇𝑟)∘𝑘)(𝑚(𝑞)). Unpacking and (23.12) therefore give the renamed node [𝑋,𝑚,(𝑇𝑟) ∘𝑘]. Substitution by 𝖵𝖺𝗋 ∘𝑟 gives instead [𝑋,𝑚,𝜆𝑥.𝑘(𝑥)[𝖵𝖺𝗋∘𝑟]], and the induction hypothesis on each continuation branch gives 𝑘(𝑥)[𝖵𝖺𝗋∘𝑟]=𝑇𝑟(𝑘(𝑥)). Thus the representatives agree pointwise. Well-definedness follows from lemma 23.10. ◻
The identity and composition laws for the source functor action now follow from theorem 23.11; the functor action used in lemma 23.5 and the monadic substitution are therefore compatible.
Let 𝑡 :𝑇𝑋, 𝑘 :𝑋 →𝑇𝐴, 𝑓 :𝐴 →𝑇𝐵, and 𝑔 :𝐵 →𝑇𝐶. Then (𝗈𝗇𝖼𝖾(𝑡;𝑘)≫=𝑓)≫=𝑔(23.20)=𝗈𝗇𝖼𝖾(𝑡;𝜆𝑥.(𝑘(𝑥)≫=𝑓)≫=𝑔)𝑎𝑠𝑠𝑜𝑐𝑖𝑎𝑡𝑖𝑣𝑖𝑡𝑦=𝗈𝗇𝖼𝖾(𝑡;𝜆𝑥.𝑘(𝑥)≫=(𝜆𝑎.𝑓(𝑎)≫=𝑔)). Neither substitution duplicates nor rewrites 𝑡.
Referenced from 2 locations
★★☆ Using only (23.25) and theorem 23.11, prove 𝑇𝗂𝖽 =𝗂𝖽 and 𝑇(𝑔 ∘𝑓) =𝑇𝑔 ∘𝑇𝑓. State exactly where left unit is used in the composition calculation.
Referenced from 3 locations
Syntactic equations at three constructors
The monad laws determine substitution and composition at the three running constructors. The following calculations expose the relevant recursive position in each case.
Ordinary choice.
For 𝑓 :𝐴 →𝑇𝐵, 𝗈𝗋(𝑡,𝑢)≫=𝑓=𝗈𝗋(𝑡≫=𝑓,𝑢≫=𝑓). The operation is algebraic because both recursive children are response continuations.
Once.
For a smart once node, 𝗈𝗇𝖼𝖾(𝑡)≫=𝑓=𝗈𝗇𝖼𝖾(𝑡;𝑓), not 𝗈𝗇𝖼𝖾(𝑡≫=𝑓). The scope body is not a continuation branch.
Local state.
For the source’s smart constructor, 𝗅𝗈𝖼𝖺𝗅(𝑛,𝑠,𝑡):=𝗅𝗈𝖼𝖺𝗅(𝑛,𝑠,𝑡;𝖵𝖺𝗋), and therefore 𝗅𝗈𝖼𝖺𝗅(𝑛,𝑠,𝑡)≫=𝑓=𝗅𝗈𝖼𝖺𝗅(𝑛,𝑠,𝑡;𝑓). The ordinary parameters 𝑛,𝑠 are stable, the local computation 𝑡 stays inside the scope, and the continuation becomes 𝑓. An implementation which changes every field under bind has confused three different parts of the signature.
Equations (23.26)–(23.28) belong to the abstract syntax monad; an operational interpretation requires a separate handler algebra.
Exact comparisons with neighboring abstractions
The words idiom, arrow, scoped operation, and higher-order operation describe different structures. Similar-looking examples are not a translation. We compare them only where a map can be written or a type obstruction can be exhibited.
From the scoped monad to an idiom
Every instance of the scoped syntax monad yields an applicative/idiom structure by the standard monadic translation 𝗉𝗎𝗋𝖾(𝑎):=𝗋𝖾𝗍𝗎𝗋𝗇𝑎,𝑢<∗>𝑣:=𝑢≫=𝜆𝑓.𝑣≫=𝜆𝑥.𝗋𝖾𝗍𝗎𝗋𝗇(𝑓(𝑥)).
The operations in (23.29) satisfy the following well-typed applicative/idiom equations. In the identity law let 𝑣 :𝑇𝐴; in homomorphism let 𝑓 :𝐴 →𝐵 and 𝑥 :𝐴; in interchange let 𝑢 :𝑇(𝐴 →𝐵) and 𝑦 :𝐴; and in composition let 𝑢 :𝑇(𝐵 →𝐶), 𝑣 :𝑇(𝐴 →𝐵), and 𝑤 :𝑇𝐴. Then 𝗉𝗎𝗋𝖾(𝗂𝖽𝐴)<∗>𝑣=𝑣,𝗉𝗎𝗋𝖾(𝑓)<∗>𝗉𝗎𝗋𝖾(𝑥)=𝗉𝗎𝗋𝖾(𝑓(𝑥)),𝑢<∗>𝗉𝗎𝗋𝖾(𝑦)=𝗉𝗎𝗋𝖾(𝜆ℎ.ℎ(𝑦))<∗>𝑢,𝗉𝗎𝗋𝖾(∘)<∗>𝑢<∗>𝑣<∗>𝑤=𝑢<∗>(𝑣<∗>𝑤). The last line is read left-associatively, with ∘(𝑓)(𝑔)(𝑥) =𝑓(𝑔(𝑥)).
Referenced from 3 locations
Proof of Proposition 23.15 — Monad-induced idiom
Proof. Expand 𝗉𝗎𝗋𝖾 and <∗> by (23.29). Identity and homomorphism reduce directly by the unit laws: 𝗉𝗎𝗋𝖾(𝗂𝖽𝐴)<∗>𝑣𝑑𝑒𝑓𝑖𝑛𝑖𝑡𝑖𝑜𝑛=𝗋𝖾𝗍𝗎𝗋𝗇(𝗂𝖽𝐴)≫=𝜆ℎ.𝑣≫=𝜆𝑥.𝗋𝖾𝗍𝗎𝗋𝗇(ℎ(𝑥))left unit=𝑣≫=𝜆𝑥.𝗋𝖾𝗍𝗎𝗋𝗇(𝑥)right unit=𝑣, and 𝗉𝗎𝗋𝖾(𝑓)<∗>𝗉𝗎𝗋𝖾(𝑥)𝑑𝑒𝑓𝑖𝑛𝑖𝑡𝑖𝑜𝑛=𝗋𝖾𝗍𝗎𝗋𝗇(𝑓)≫=𝜆ℎ.𝗋𝖾𝗍𝗎𝗋𝗇(𝑥)≫=𝜆𝑎.𝗋𝖾𝗍𝗎𝗋𝗇(ℎ(𝑎))left unit twice=𝗋𝖾𝗍𝗎𝗋𝗇(𝑓(𝑥)).
For interchange, put 𝖾𝗏𝑦(ℎ):=ℎ(𝑦). Both sides reduce to the same term: 𝑢<∗>𝗉𝗎𝗋𝖾(𝑦)(23.29)=𝑢≫=𝜆ℎ.𝗋𝖾𝗍𝗎𝗋𝗇(𝑦)≫=𝜆𝑎.𝗋𝖾𝗍𝗎𝗋𝗇(ℎ(𝑎))left unit=𝑢≫=𝜆ℎ.𝗋𝖾𝗍𝗎𝗋𝗇(ℎ(𝑦)),𝗉𝗎𝗋𝖾(𝖾𝗏𝑦)<∗>𝑢(23.29)=𝗋𝖾𝗍𝗎𝗋𝗇(𝖾𝗏𝑦)≫=𝜆𝑒.𝑢≫=𝜆ℎ.𝗋𝖾𝗍𝗎𝗋𝗇(𝑒(ℎ))left unit=𝑢≫=𝜆ℎ.𝗋𝖾𝗍𝗎𝗋𝗇(ℎ(𝑦)).
For composition, factor both sides through the common normal form 𝑁:=𝑢≫=𝜆𝑓.𝑣≫=𝜆𝑔.𝑤≫=𝜆𝑥.𝗋𝖾𝗍𝗎𝗋𝗇(𝑓(𝑔(𝑥))). Application associates to the left. Put 𝑃:=𝗉𝗎𝗋𝖾(∘)<∗>𝑢<∗>𝑣. Expansion of (23.29), followed by left unit, gives 𝑃=𝑢≫=𝜆𝑓.𝑣≫=𝜆𝑔.𝗋𝖾𝗍𝗎𝗋𝗇(𝑓∘𝑔). Expanding the final application and reassociating therefore yields 𝑃<∗>𝑤def., assoc.=𝑢≫=𝜆𝑓.𝑣≫=𝜆𝑔.𝑤≫=𝜆𝑥.𝗋𝖾𝗍𝗎𝗋𝗇((𝑓∘𝑔)(𝑥))𝑐𝑜𝑚𝑝𝑜𝑠𝑖𝑡𝑖𝑜𝑛=𝑁. On the right, first expand the inner application and then reassociate: 𝑢<∗>(𝑣<∗>𝑤)𝑑𝑒𝑓𝑖𝑛𝑖𝑡𝑖𝑜𝑛=𝑢≫=𝜆𝑓.(𝑣<∗>𝑤)≫=𝜆𝑦.𝗋𝖾𝗍𝗎𝗋𝗇(𝑓(𝑦))def., assoc.=𝑢≫=𝜆𝑓.𝑣≫=𝜆𝑔.𝑤≫=𝜆𝑥.𝗋𝖾𝗍𝗎𝗋𝗇(𝑓(𝑔(𝑥)))definition of 𝑁=𝑁. ◻
Equation (23.29) is the exact one-way translation used here. We do not infer a converse from the applicative interface: 𝗉𝗎𝗋𝖾 and <∗> do not themselves define an operation of bind’s dependent type. This is a signature boundary, not a nondefinability theorem. Lindley’s comparison of idioms, arrows, and monads is used only as neighboring vocabulary, not as a theorem about our scoped signature [Lin14].
The Kleisli arrow
For the arrow comparison, use the exact Kleisli category of the monad and its cartesian product action; no abstract Arrow law package is imported. Take an arrow from 𝐴 to 𝐵 to be a function 𝐴 →𝑇𝐵, and define 𝖺𝗋𝗋(𝑓)(𝑎):=𝗋𝖾𝗍𝗎𝗋𝗇(𝑓(𝑎)),(𝑔⋄𝑓)(𝑎):=𝑓(𝑎)≫=𝑔,𝖿𝗂𝗋𝗌𝗍(𝑓)(𝑎,𝑐):=𝑓(𝑎)≫=𝜆𝑏.𝗋𝖾𝗍𝗎𝗋𝗇(𝑏,𝑐).
Let 𝑝 :𝐴 →𝑇𝐵, 𝑞 :𝐵 →𝑇𝐶, and 𝑟 :𝐶 →𝑇𝐷 be Kleisli arrows; let 𝑓 :𝐴 →𝐵 and 𝑔 :𝐵 →𝐶 be ordinary maps; and let 𝐸 be any set. The operations in (23.30) satisfy 𝖺𝗋𝗋(𝗂𝖽𝐵)⋄𝑝=𝑝,𝑝⋄𝖺𝗋𝗋(𝗂𝖽𝐴)=𝑝,(𝑟⋄𝑞)⋄𝑝=𝑟⋄(𝑞⋄𝑝),𝖺𝗋𝗋(𝑔∘𝑓)=𝖺𝗋𝗋(𝑔)⋄𝖺𝗋𝗋(𝑓),𝖿𝗂𝗋𝗌𝗍𝐸(𝖺𝗋𝗋(𝑓))=𝖺𝗋𝗋(𝜆(𝑎,𝑒).(𝑓(𝑎),𝑒)),𝖿𝗂𝗋𝗌𝗍𝐸(𝑞⋄𝑝)=𝖿𝗂𝗋𝗌𝗍𝐸(𝑞)⋄𝖿𝗂𝗋𝗌𝗍𝐸(𝑝). The first four are the Kleisli-category laws; the last two are the product action equations used in this comparison. The subscript 𝐸 only records the unchanged product component and is normally suppressed.
Referenced from 3 locations
Proof of Proposition 23.16 — Kleisli category and product action
Proof. All equations are pointwise. For the left identity, (𝖺𝗋𝗋(𝗂𝖽𝐵)⋄𝑝)(𝑎)(23.30)=𝑝(𝑎)≫=𝗋𝖾𝗍𝗎𝗋𝗇right unit=𝑝(𝑎). For the right identity, (𝑝⋄𝖺𝗋𝗋(𝗂𝖽𝐴))(𝑎)(23.30)=𝗋𝖾𝗍𝗎𝗋𝗇(𝑎)≫=𝑝left unit=𝑝(𝑎). Ordinary composition is preserved because (𝖺𝗋𝗋(𝑔)⋄𝖺𝗋𝗋(𝑓))(𝑎)(23.30)=𝗋𝖾𝗍𝗎𝗋𝗇(𝑓(𝑎))≫=(𝗋𝖾𝗍𝗎𝗋𝗇∘𝑔)left unit=𝗋𝖾𝗍𝗎𝗋𝗇(𝑔(𝑓(𝑎)))(23.30)=𝖺𝗋𝗋(𝑔∘𝑓)(𝑎). Associativity is ((𝑟⋄𝑞)⋄𝑝)(𝑎)(23.30)=𝑝(𝑎)≫=(𝜆𝑏.𝑞(𝑏)≫=𝑟)associativity=(𝑝(𝑎)≫=𝑞)≫=𝑟(23.30)=(𝑟⋄(𝑞⋄𝑝))(𝑎). For the first product equation, 𝖿𝗂𝗋𝗌𝗍𝐸(𝖺𝗋𝗋(𝑓))(𝑎,𝑒)(23.30)=𝗋𝖾𝗍𝗎𝗋𝗇(𝑓(𝑎))≫=𝜆𝑏.𝗋𝖾𝗍𝗎𝗋𝗇(𝑏,𝑒)left unit=𝗋𝖾𝗍𝗎𝗋𝗇(𝑓(𝑎),𝑒)(23.30)=𝖺𝗋𝗋(𝜆(𝑎,𝑒).(𝑓(𝑎),𝑒))(𝑎,𝑒). For the second product equation, define 𝑁𝑒:=𝑝(𝑎)≫=𝜆𝑏.𝑞(𝑏)≫=𝜆𝑐.𝗋𝖾𝗍𝗎𝗋𝗇(𝑐,𝑒). The left side reduces as follows: 𝖿𝗂𝗋𝗌𝗍𝐸(𝑞⋄𝑝)(𝑎,𝑒)(23.30)=(𝑞⋄𝑝)(𝑎)≫=𝜆𝑐.𝗋𝖾𝗍𝗎𝗋𝗇(𝑐,𝑒)(23.30)=(𝑝(𝑎)≫=𝑞)≫=𝜆𝑐.𝗋𝖾𝗍𝗎𝗋𝗇(𝑐,𝑒)associativity=𝑁𝑒. The right side reduces to the same term: (𝖿𝗂𝗋𝗌𝗍𝐸(𝑞)⋄𝖿𝗂𝗋𝗌𝗍𝐸(𝑝))(𝑎,𝑒)(23.30)=𝖿𝗂𝗋𝗌𝗍𝐸(𝑝)(𝑎,𝑒)≫=𝖿𝗂𝗋𝗌𝗍𝐸(𝑞)(23.30)=(𝑝(𝑎)≫=𝜆𝑏.𝗋𝖾𝗍𝗎𝗋𝗇(𝑏,𝑒))≫=𝖿𝗂𝗋𝗌𝗍𝐸(𝑞)associativity=𝑝(𝑎)≫=𝜆𝑏.𝗋𝖾𝗍𝗎𝗋𝗇(𝑏,𝑒)≫=𝖿𝗂𝗋𝗌𝗍𝐸(𝑞)left unit=𝑝(𝑎)≫=𝜆𝑏.𝖿𝗂𝗋𝗌𝗍𝐸(𝑞)(𝑏,𝑒)(23.30)=𝑁𝑒. Function extensionality completes each equation. ◻
This construction is one-way. An arbitrary arrow interface does not by itself select a canonical family of carriers 𝑇𝐴, a return injection 𝐴 →𝑇𝐴, or the explicit scoped constructors (23.6). No converse reconstruction is claimed.
Scoped operations versus higher-order operations
The scoped signature (23.4) has one intermediate result set 𝑋 at a scope node. Consequently every owned computation 𝑚(𝑞):𝑇𝑋(𝑞∈𝑄𝑠) returns the same 𝑋, and the outside continuation has domain exactly 𝑋: 𝑘:𝑋→𝑇𝐴. A higher-order operation has a different interface. Its fork positions may have result sets 𝐵𝑞, while the operation itself has an independently specified response set 𝑅. Its node data therefore have the shape 𝜓𝑞:𝐻𝐵𝑞(𝑞∈𝑄),𝜅:𝑅→𝐻𝐴. Here 𝐻 names the later higher-order syntax only for this comparison; it is not identified with 𝑇.
To isolate the shape question, suppose a sortwise translation 𝜏𝑍:𝐻𝑍→𝑇𝑍 is fixed for every set 𝑍. This is an explicit assumption, not a translation theorem about the later calculus. Put 𝑋:=∐𝑞∈𝑄𝐵𝑞,̂𝜓𝑞:=𝜏𝐵𝑞(𝜓𝑞),̂𝜅(𝑟):=𝜏𝐴(𝜅(𝑟)). A first failed counterexample points only to the heterogeneous sets 𝐵𝑞. That objection is too weak: functorial renaming gives 𝑇𝗂𝗇𝑞(̂𝜓𝑞):𝑇𝑋(𝑞∈𝑄). Thus tags repair heterogeneity. They do not repair the continuation: ̂𝜅 has domain 𝑅, while a scoped node over the coproduct carrier needs a continuation with domain 𝑋.
For sets 𝑋 and 𝑅, a structural continuation translation from response set 𝑅 to carrier 𝑋 is a family Φ𝑌:(𝑅→𝑌)→(𝑋→𝑌) indexed by sets 𝑌, natural in the continuation codomain: for every 𝑢 :𝑌 →𝑍 and ℓ :𝑅 →𝑌, 𝑢∘Φ𝑌(ℓ)=Φ𝑍(𝑢∘ℓ). Naturality says that changing what happens after the continuation commutes with the conversion of its domain from 𝑅 to 𝑋. It rules out a conversion which inspects or invents codomain-specific syntax.
Referenced from 2 locations
Structural continuation translations from 𝑅 to 𝑋 are in bijection with functions 𝜌 :𝑋 →𝑅. The two directions are Φ𝑌(ℓ)=ℓ∘𝜌,𝜌=Φ𝑅(𝗂𝖽𝑅).
Referenced from 4 locations
Proof of Proposition 23.18 — Continuation-adapter criterion
Proof. Given 𝜌 :𝑋 →𝑅, precomposition defines (23.33). For 𝑢 :𝑌 →𝑍, 𝑢∘Φ𝑌(ℓ)𝑑𝑒𝑓𝑖𝑛𝑖𝑡𝑖𝑜𝑛=𝑢∘ℓ∘𝜌𝑑𝑒𝑓𝑖𝑛𝑖𝑡𝑖𝑜𝑛=Φ𝑍(𝑢∘ℓ), so (23.34) holds.
Conversely, let Φ satisfy the naturality equation and put 𝜌:=Φ𝑅(𝗂𝖽𝑅). For any set 𝑌 and map ℓ :𝑅 →𝑌, apply naturality from codomain 𝑅 to codomain 𝑌, with post-map ℓ and continuation 𝗂𝖽𝑅. Then ℓ∘𝜌𝑑𝑒𝑓𝑖𝑛𝑖𝑡𝑖𝑜𝑛=ℓ∘Φ𝑅(𝗂𝖽𝑅)(23.34)=Φ𝑌(ℓ∘𝗂𝖽𝑅)identity law=Φ𝑌(ℓ). Hence every structural translation is precomposition with the recovered adapter. Recovering an adapter from precomposition returns the original 𝜌, and reconstructing Φ from the recovered adapter returns the original family by the displayed calculation. ◻
The criterion gives a genuine counterexample. Take two fork positions with 𝐵𝐿=ℕ,𝐵𝑅=𝟐,𝑅=∅. At the level of the interface (23.31), take 𝐻 =𝖨𝖽 and 𝜏𝑍 =𝖵𝖺𝗋 :𝑍 →𝑇𝑍. Choose 𝜓𝐿 =0, 𝜓𝑅 =𝖿𝖺𝗅𝗌𝖾, and use the unique continuation Here ∅ is the empty response set, corresponding to the empty type 0 used for response domains in chapter 22. Thus ∅ →𝐴 is a singleton function space. The higher-order node is therefore well formed, and all of its computation-valued fields have the assumed translation. The coproduct carrier 𝑋 =ℕ +𝟐 makes the fork homogeneous, but no function 𝑋 →∅ exists. More generally, any common carrier 𝐶 reached by maps from both inhabited fork-result sets is inhabited, so it cannot admit an adapter 𝐶 →∅. By proposition 23.18, there is no structural conversion of this node to the scoped shape using only functorial fork translations and a natural continuation conversion.
There are restricted positive bridges. Suppose the sortwise translation 𝜏 above is fixed, a scoped symbol 𝑠 has 𝑄𝑠 =𝑄, a matching ordinary parameter 𝑝 :𝑃𝑠 and an operation-specific adapter 𝜌 :𝑋 →𝑅 are supplied. Then the translated node is exactly 𝖲𝖼𝗈𝗉𝖾𝑠(𝑝;𝑋;𝜆𝑞.𝑇𝗂𝗇𝑞(𝜏𝐵𝑞(𝜓𝑞));̂𝜅∘𝜌). Equation (23.32) translates the fork positions and (23.35) changes the continuation domain. Taking 𝑅 =𝑋 and 𝜌 =𝗂𝖽𝑋 is the simplest case. The adapter is additional operation-specific signature data; it is absent from an arbitrary higher-order operation. This conditional node translation proves neither inclusion nor equivalence of the two calculi, and it transfers no elaboration theorem from the separate higher-order system.
★☆☆ Let 𝐹 :𝐴 →𝑇𝐵 have the scoped form 𝐹(𝑎)=𝗈𝗇𝖼𝖾(𝑡𝑎;𝑘𝑎),𝑡𝑎:𝑇𝑋,𝑘𝑎:𝑋→𝑇𝐵. Calculate 𝖿𝗂𝗋𝗌𝗍(𝐹)(𝑎,𝑐) from (23.30) and then by (23.20). Identify the unchanged scoped computation and the new outside continuation.
Referenced from 3 locations
Sources and mathematical scope
The syntax (23.5)–(23.6), the explicit-continuation reading, the source bind clause (23.18), and the nondeterminism, exceptions, and local-state signatures come from Piróg, Schrijvers, Wu, and Jaskelioff [PSWJ18]. The algebraicity obstruction in (23.2)– (23.3) is their motivating calculation. This chapter proves the elementwise reindexing, substitution equations, and monad laws locally rather than using a citation as a proof. The reindexing equation in definition 23.4 is the elementwise form of the explicit-substitution quotient in Section 3 of that source.
Plotkin and Power characterize the first-order commutation boundary recalled from chapter 22 [PP03]. Lindley gives the neighboring idiom/arrow terminology [Lin14]; the concrete translations (23.29)–(23.30) are proved directly here.
Operational handlers require an evaluation relation and typing judgment not present in this syntax, so their safety theorems begin from additional data. Likewise, higher-order modular elaboration is a separate calculus rather than a metatheorem of 𝑇.
Suggested first pass.
Exercise 23.10, Exercise 23.12, Exercise 23.14 form the suggested first pass.
★★☆ Give a polynomial scoped signature for a unary 𝗍𝗋𝖺𝗇𝗌𝖺𝖼𝗍𝗂𝗈𝗇 constructor with no ordinary parameters. For 𝑀 :𝑇𝑋, 𝑘 :𝑋 →𝑇𝐴, and 𝑓 :𝐴 →𝑇𝐵, write the explicit node 𝗍𝗋𝖺𝗇𝗌𝖺𝖼𝗍𝗂𝗈𝗇(𝑀;𝑘). Then calculate 𝗍𝗋𝖺𝗇𝗌𝖺𝖼𝗍𝗂𝗈𝗇(𝑀;𝑘)≫=𝑓 and compare it with the false-algebraicity candidate that pushes both the stored continuation and the new bind into the body and resets the outside continuation, 𝗍𝗋𝖺𝗇𝗌𝖺𝖼𝗍𝗂𝗈𝗇(𝑀≫=(𝜆𝑥.𝑘(𝑥)≫=𝑓);𝖵𝖺𝗋). Also instantiate the all-fields traversal (23.16) in the endomorphic homogeneous case 𝑋 =𝐴 =𝐵. Your answer must distinguish its general type failure from the semantic transaction failure of false algebraicity in (23.1).
Referenced from 4 locations
★★☆ Let 𝑠 have two scoped positions and no ordinary parameters. Suppose ℎ :𝑋 →𝑌, 𝑚1,𝑚2 :𝑇𝑋, and 𝑘 :𝑌 →𝑇𝐴. Starting only from (23.12), show [𝑋,(𝑚1,𝑚2),𝑘∘ℎ]=[𝑌,(𝑇ℎ(𝑚1),𝑇ℎ(𝑚2)),𝑘]. Now substitute 𝑓 :𝐴 →𝑇𝐵 on both sides and prove that the resulting representatives are again related by the same ℎ. Do not appeal to lemma 23.10 as a black box; reproduce its one-step calculation for this binary case.
Referenced from 3 locations
★★☆ Use Γ𝑋 =𝑋 ×𝑋𝐸 to write an elementwise catch node with protected computation 𝑀 :𝑇𝑋, recovery family 𝐻 :𝐸 →𝑇𝑋, and outside continuation 𝑘 :𝑋 →𝑇𝐴. Let 𝑓 :𝐴 →𝑇𝐵 and 𝑔 :𝐵 →𝑇𝐶. Calculate one and then two successive substitutions. Identify which of 𝑀,𝐻,𝑘 changes at each step, and verify the associativity equation for this node without referring to an interpretation of exceptions.
Referenced from 4 locations
★★☆ For 𝑡 :𝑇𝐴, start from the elementwise smart constructor (23.15), pack it with (23.13), and obtain its canonical member of 𝑇(𝑇𝐴). Then substitute 𝑓 :𝐴 →𝑇𝐵, canonicalize again, and derive the nested source clause (23.18) for this unary signature. Every use of functoriality or reindexing must be named.
Referenced from 3 locations
★★★ A later higher-order operation has two fork positions with result sets 𝐵𝐿 =ℕ and 𝐵𝑅 =𝟐, and an independent response set 𝑅. Its data are 𝜓𝐿 :𝐻ℕ, 𝜓𝑅 :𝐻𝟐, and 𝜅 :𝑅 →𝐻𝐴. Assume a sortwise computation translation 𝜏𝑍 :𝐻𝑍 →𝑇𝑍. First use 𝑋 =ℕ +𝟐 and the injections to homogenize the translated fork computations, and translate the continuation pointwise to ̂𝜅 :𝑅 →𝑇𝐴. Then prove directly that a family Φ𝑌:(𝑅→𝑌)→(𝑋→𝑌) natural in 𝑌 exists exactly when an adapter 𝜌 :𝑋 →𝑅 is supplied. Instantiate the result at 𝑅 =∅ to obtain a counterexample. Finally give the restricted positive bridge for 𝑅 =𝑋 and 𝜌 =𝗂𝖽𝑋, and identify the additional signature data used by that bridge.
Referenced from 4 locations
★★★ Practical project.scoped-substitution Implement a finite executable model of ordinary and scoped syntax using the bundled Kappa compiler. The representation must make ordinary parameters, scoped computations, and explicit continuations different fields. Maintain this invariant: substitution descends through every ordinary branch, preserves every ordinary parameter and scoped computation, and composes the new post-computation on the right of the stored continuation.
The observable result is the following exact six-line semantic report followed by its summary line:
PASS ordinary substitution descends through ordinary branches
PASS scoped substitution preserves ordinary parameters
PASS scoped substitution leaves the scoped computation untouched
PASS scoped substitution composes only the continuation
PASS tested substitution equations and monad laws hold
PASS false algebraicity and all-fields traversal are distinguished
All 6 scoped-operations corpus cases passed.
The decidable acceptance test must check all of the following:
ordinary substitution descends through nested ordinary choice;
local-scope ordinary parameters are unchanged;
a once body is unchanged by outer substitution;
continuation composition preserves left-to-right order;
the tested left-unit, right-unit, and associativity instances hold; and
deliberately constructed false-algebraicity and all-fields trees are pairwise distinct from the correct scoped-substitution tree and from each other.
Then test at least three separate semantic mutations: one which pushes substitution into the scoped body, one which corrupts an ordinary scoped parameter, and one which reverses continuation composition. Every mutant must still parse and type-check but fail the semantic oracle. Restore the accepted source and require the frozen six-case oracle again. Appendix E records the commands, digests, and the implementation-evidence boundary.
Referenced from 5 locations