Lectures onType Theory
ch:effect-rows: ch:effect-rows
appendix sectionsolutions

ch:effect-rows: ch:effect-rows

exercise 25.1.

Fix the tail symbol and interpret a row prefix as its finite multiplicity function m:LabelN. Then m,μ()=2+mμ(),mμ()=1+mμ(). Natural-number cancellation would equate 2 and 1, so the rows are not equivalent. Operationally, a handler can consume the first occurrence and re-perform in its clause. Its input and output effects are therefore ,μ and μ. Contraction would identify those types and erase the fact that the outer request remains observable.

exercise 25.2.

Put ν=get,putξ. The fallback instance has premises Γe:Int!raiseν,Γ,x:Intreturn x:Int!ν,Γ,p:Error,k:0νIntreturn d:Int!ν. Thus C-Handle changes Int!raise,get,putξ to Int!get,putξ.

For the rethrower put ε=raise,get,putξ. Its premises are Γe:Int!raiseε,Γ,x:Intreturn x:Int!ε,Γ,p:Error,k:0εIntperform raise p to z.kz:Int!ε. The last premise follows from C-Op at result 0 and C-To; no value of 0 is required. This instance changes Int!raise,raise,get,putξ to Int!ε.

exercise 25.3.

Write the initial computation as M0. Its innermost handler is H0, so H-Forward gives M0M1=handle(perform  v to y.handle R[return y] with H0) with H1. For M0, lemma 25.6 has outside context E=handle [] with H1, request context R, and nearest handler H0. In M1 the request context immediately inside H1 is R1=[] to y.handle R[return y] with H0. Hence H-Op gives M1e[v/p,(λz.handle R1[return z] with H1)/k]. The first body is syntactically handle R[perform  v] with H0; because it contains a handler frame, it cannot be R[perform  v] for handler-free R. Thus the outer H-Op is not an initial root.

exercise 25.4.

Invert the typing of handle R[perform  v] with H. If H handles 1,,n and has output row ε, the handler premise and typed hole give 1,,nεδ,{1,,n}. The second part of cancellation exposes εε. For fresh y:R, C-Return types the replacement hole return y:R!δ. Request-context replacement therefore reconstructs the input premise, and C-Handle gives Γ,y:Rhandle R[return y] with H:B!ε. Choose ε as the tail in C-Op; the forwarded request then has effect εε. C-To with the displayed continuation types the reduct at B!ε, exactly the type of the redex.

exercise 25.5.

For 1μ2μ with 12, rewriting the right row for 1 skips 2, chooses fresh ν, and returns S1=[μ1ν],ε3=2ν. Since tail(μ)=μdom(S1), the guard fails before the recursive equation can recreate the original shape.

For 1μ2,1ν, rewriting finds the visible 1 after skipping 2, returns the identity and residual 2ν, and the tail equation is μ2ν. Hence the MGU is [μ2ν].

exercise 25.6.

Expose the leftmost raise on the right. It skips get and leaves get,raiseν. Exposing get next leaves raiseν. The residual equation is therefore μraiseν, so S=[μraiseν] is an MGU. Both rows become raise,get,raiseν. If T is any other unifier, cancellation of one raise and one get gives TμraiseTν. Define Q to agree with T away from μ; then T=QS on μ,ν.

exercise 25.7.

After the inserted request, name the final-return, log, put, and get tails ρr,ρl,ρp,ρg, and write εf for the single latent row of the lambda-bound callback. Working outward from the return, W solves logρlρrρrlogρlputρplogρlρlputξ,ρplogξεfput,logξεfput,logξgetρgput,logξξgetμ,ρgput,logμ. Thus every sequence has common effect Lμ=get,put,logμ, modulo exchange, and εf=Lμ. The wrapper therefore has principal scheme μ.(1LμInt)LμInt. Instantiating μraiseν gives exactly one raise in both callback and body: get,put,log,raiseν. In the separate let-polymorphic trace, by contrast, the occurrence of f first receives its own fresh instance of the quantified callback tail and W then unifies that instance with the surrounding sequence. The monomorphic parameter has only εf, so its callback and body cannot receive independently quantified row tails. Concretely, the unmodified trace above instantiates the callback’s private ν with get,putμ and obtains Eμ=get,put,raiseμ. There raise comes from the callback scheme; in the present wrapper it comes from instantiating the one shared tail, while the inserted log is a fixed label of the body.

exercise 25.8.

For the body perform ask (), W returns S0=id,A0=Env,ε0=askμ0. Choose fresh β,μ. The return clause return x reports Env!δr; its two solve steps bind βEnv and δrμ. The operation clause is inferred under u:1,k:EnvμEnv. Application kr unifies its fresh domain with Env, its fresh result with Env, and its latent row with μ; the two clause-result solves are then identities. The final input equation askμ0askμ binds μ0μ. Hence r:Envhr:Env!μ, and the principal computation scheme relative to that context is μ.(Env!μ). The continuation annotation comes from k:Raskμβ: it is the handler output row. Giving it askμ would incorrectly reintroduce the consumed occurrence on every resumption and would not be a premise of C-Handle.

exercise 25.9.

Set erasure maps both raise,raiseν and raiseν to {raise}ν. Thus it cannot record that the rethrower consumed one occurrence. If a fallback output tail contains no raise, its input erases to {raise}ν and its output to ν, so ordinary set difference still distinguishes them. The erased handler is nevertheless well typed. For the rethrower, Ein{raise}=ν{raise}ν=Eout, which is exactly the target rule’s inclusion premise. What fails is faithful representation: the two source annotations above have the same support, so the target cannot say that exactly one occurrence was consumed. The fallback still changes support and therefore retains that coarser distinction.

exercise 25.10.

Use unique rows with a constrained extension μ well formed only under μ. The one-operation handler rule becomes Γe:A!μμΓ,x:Aer:B!μΓ,p:P,k:RμBe:B!μΓhandle e with H:B!μ. W’s final equation is still ε0μ, but solving it generates and must discharge the predicate μ. A principality proof now needs: sound substitutions for equations and lacks predicates; completeness of solving relative to a stated constraint theory; sound and complete constraint entailment; and factorization of every satisfying substitution through the reported substitution together with a residual constraint set. Ordinary unconstrained MGU factorization is no longer enough.

exercise 25.11.

Take a searched label and a different skipped label m: ε=m,mρ. If Tεδ, the two Rw-Skip steps reduce exposure to ρ. Since m, cancellation and exchange give a row δ such that Tρδ,δm,mδ. Apply the induction hypothesis to the first equality. If exposure of ρ returns (S,ρ), there is Q with T=QS on ρ and δQρ. Exchange gives m,m,Qρ,m,mQρ, so the residual is m,mρ and the same Q is the factor. Cancellation removes the one exposed but retains both m occurrences. Treating the prefix as a set would collapse them and could not justify this residual equality; multiplicity is used exactly there.

exercise 25.12.

For one operation, inversion supplies declarative body, return, and operation derivations with common output Tβ!Tμ and input Tμ. The body induction hypothesis gives T=R0Q0 after Q0=S0. The return-clause hypothesis factors through SrQ0; the residual solves Brβ and δrμ. Two applications of MGU factorization produce residuals Rr1,Rr with T=RrQr.

Infer the operation clause under p:P,k:Rμβ. Its induction hypothesis gives a residual after S1Qr; inversion says it solves B1β and δ1μ. The corresponding MGUs produce Q11,Q1c and a residual R1 with T=R1Q1c. Finally the inverted body premise solves ε0μ. Its MGU gives Q and R with T=RQ. The rules paired with these four stages are respectively the body induction hypothesis, return-clause C-Handle premise, operation-clause premise, and handler-input premise; every equation uses the MGU theorem, so Q is principal.

exercise 25.13.

Let H0 omit raise and let H1 handle it. If the inner body has effect raiseδ, forwarding inversion and cancellation force the output of H0 to be equivalent to raiseδ. The first root is therefore typed by H-Forward at that same row. Its reduct exposes the request immediately inside H1, whose H-Op premise consumes that occurrence and returns at the outer output row δ.

Operationally the nearest-handler decompositions are exactly those in the solution to exercise 25.3; there is no competing outer root. If the final row is , progress permits only a return or a step: an exposed raise would require positive raise-multiplicity in the final row, contradicting its zero multiplicity. Thus forwarding cannot turn a fully handled closed program into an unhandled terminal request.

exercise 25.14.

For unique rows use an exposure judgment Cε(S,ε;C) whose variable-tail rule chooses fresh ν, returns S=[μν], and adds ν to C. Head and skip rules retain and normalize the constraints; every extension carries the well-kindedness premise that its head is absent from its tail. Factorization must say that if T satisfies C and exposes , then T=QS on the input variables, Q satisfies C, and the target residual is Qε.

The one-operation W handler case infers the body and clauses as in the chapter, then solves ε0μ together with μ. Its result is principal only relative to the residual lacks constraint: every other typed instance factors through the substitution and entails that residual. Duplicate rows avoid precisely this constraint judgment, its entailment theorem, and the constraint component of factorization; their exposure result (25.11) is an ordinary substitution MGU.

Exercise 31.9.

Let w0=,w1=:(m1,h1,w0)w0,w2=:(m2,h2,w1)w1. Selection gives w2.=(m2,h2,w1). The newest entry therefore yields to m2, not m1, using a clause from h2. Internal safety requires both prompts to be reachable from source-generated handler steps; theorem 31.28 then forbids reusing m1 for the inner prompt. In the displayed Fpw perform contraction, the lookup binds w2.=(m2,h2,w1) but the reduct uses only m2 and h2. The retained third component belongs to the later tail-resumptive optimization, whose under rules are outside the frozen card.

Exercise 31.10.

One suitable type is recover:(1{raise}βA)(Eβ{raise}A)1βA. The recovery clause checks its handler body under φ=β{raise}. Boolean algebra gives φ{raise}=(β{raise}c){raise}B, which is the Ex-Without premise. A duplicate-row variable μ may be instantiated by a row containing raise, so it entails no absence. A positive extension μ only adds an occurrence; it places no constraint on the tail. The negative property therefore requires the separate Boolean row theory.

Search the book

Type to search the local edition.