Lectures onType Theory
ch:scoped-operations: ch:scoped-operations
appendix sectionsolutions

ch:scoped-operations: ch:scoped-operations

Exercise 23.1.

The body M writes s0+1 and returns 7. The continuation k is pure and returns 8. Thus the scope boundary is not observed: transaction(M)=kcommit s0+1,then return 8,transaction(M=k)return 8 inside the transaction,then commit s0+1. The original k raises. On the left of (23.1) that raise occurs after the transaction has committed; on the right it occurs before the transaction closes and therefore triggers rollback. Algebraicity is a universal equation in the continuation. Finding one continuation k for which the two sides agree proves nothing about the failing continuation k, which is already a counterexample to the universal law.

Exercise 23.2.

Take ordinary operation symbols O={fail,or} and one scoped symbol S={once}. One convenient polynomial presentation is oPoRofail10or1{L,R}sPsQsonce11. Hence their elementwise formation data are Opfail(,k):TA(k:0TA),Opor(,k):TA(k:{L,R}TA),Scopeonce(;X;m;k):TA(X:Set, m:1TX, k:XTA). The last constructor is taken modulo the reindexing equation (23.12). The first two polynomial summands give 1+X×X, and the scoped polynomial summand gives the unary functor ΓXX.

Exercise 23.3.

For raise, take one ordinary operation family parameterized by the exception: Praise=E and Rraise=0. Its polynomial summand is therefore E×X0E.

For catch, take one scoped symbol with Pcatch=1 and Qcatch=1+E. Then X1+EX×XE, so the distinguished left position stores the protected computation and the e-position stores the recovery computation for exception e. Every position has type TX for one common intermediate set X. In particular, the protected computation and all recovery computations must return the same intermediate result type before the outside continuation is entered.

Exercise 23.4.

The canonical representative is [TA,m,idTA],m(L)=Tk(m(L)),m(R)=Tk(m(R)). Now suppose k=kh. Packing the original representative gives pack[X,m,k](q)=(23.13)T(kh)(m(q))=functoriality of TTk(Th(m(q))). Packing the reindexed representative gives exactly pack[Y,λq.Th(m(q)),k](q)=(23.13)Tk(Th(m(q))). The two packed families agree pointwise at L and R.

Exercise 23.5.

By the ordinary clause of explicit substitution, or(Var(1),Var(5))[f]=(23.17)or(f(1),f(5))=definition of for(or(Var(10),Var(11)),Var(50)). There are two or-nodes. The outer node is the original choice; the inner left node came from the replacement computation f(1).

Exercise 23.6.

The correct calculation is once(t)[f]=(23.20)once(t;f)=definition of onceScopeonce(;A;λ_.or(Var(1),Var(5));f). The original scoped choice tree is unchanged; f is stored as the outside continuation.

Both bad candidates transform the body to t[f]=(23.17)or(or(Var(1),Var(2)),or(Var(5),Var(6))). Those two new inner or-nodes have been moved under once. False algebraicity produces once(t[f];Var), so it loses f from the outside continuation. The all-fields traversal (23.16) instead produces once(t[f];f): it transforms the body and also composes after the scope. These two erroneous trees are therefore distinct.

Exercise 23.7.

Definition 23.9 gives local(n,s,t;k)[f]=(23.21)local(n,s,t;λx.k(x)[f]). Writing the first three fields of the displayed result as (nf,sf,tf), constructor injectivity gives (nf,sf,tf)=(n,s,t). An implementation which changed an ordinary parameter would violate the first two components; one which descended into the scoped body would violate the third. Neither conclusion depends on an interpretation of local state.

Exercise 23.8.

By (23.25) and right identity, Tid(t)=(23.25)t[Varid]=function identityt[Var]=(23.22b)t. For f:AB and g:BC, Tg(Tf(t))=(23.25)t[Varf][Varg]=substitution compositiont[λa.Var(f(a))[Varg]]=left unitt[λa.Var(g(f(a)))]=(23.25)T(gf)(t). Left unit is used exactly in the third line, where substitution into the returned variable Var(f(a)) collapses to Var(g(f(a))).

Exercise 23.9.

By the definition of first, first(F)(a,c)=(23.29)F(a)=λb.return(b,c)=definition of Fonce(ta;ka)=λb.return(b,c)=(23.20)once(ta;λx.ka(x)=λb.return(b,c)). The owned computation remains exactly ta:TX. The outside continuation changes from ka to xka(x)=λb.return(b,c), which pairs the final result with the untouched component c only after the scope has closed.

Exercise 23.10.

Take a single scoped symbol transaction with Ptransaction=1 and Qtransaction=1. Its scoped functor is therefore the identity. For M:TX and k:XTA, write transaction(M;k):=Scopetransaction(;X;λ_.M;k). Correct substitution gives transaction(M;k)=f=(23.20)transaction(M;λx.k(x)=f). The body M is unchanged.

The false-algebraicity candidate is transaction(M=(λx.k(x)=f);Var). It is body-only: it moves the stored continuation and the new bind into the rollback region, then loses them from the outside continuation. Specializing k=Var gives exactly the failure exhibited by (23.1).

By contrast, the all-fields traversal (23.16) tries to transform both M:TX and the outside continuation. It is ill typed unless X=A=B. In that endomorphic homogeneous case it duplicates the post-computation: it moves f into the body and also retains it after the scope. Thus the type failure belongs to the generic all-fields clause, whereas false algebraicity is typed but has the wrong transactional boundary.

Exercise 23.11.

For Qs={1,2}, equation (23.12) with m(1)=m1 and m(2)=m2 is exactly [X,(m1,m2),kh]=(23.12)[Y,(Th(m1),Th(m2)),k]. Let f:ATB and put kf(y)=k(y)[f]. Substitution on the left produces [X,(m1,m2),kfh], while substitution on the right produces [Y,(Th(m1),Th(m2)),kf]. These are related by the same generator (23.12). The two scoped computations remain untouched throughout; only the outside continuation changes.

Exercise 23.12.

Write Q=1+E, with protected position and recovery positions e:E. Define the family m():=M,m(e):=H(e). The catch node is C:=Scopecatch(;X;m;k). For f:ATB, C=f=(23.20)Scopecatch(;X;m;λx.k(x)=f). Neither M nor any H(e) changes. A second bind by g:BTC gives the calculation Scopecatch(;X;m;λx.(k(x)=f)=g)=associativity in every branchScopecatch(;X;m;λx.k(x)=(λa.f(a)=g)). The last term is the one-step substitution by the composite continuation. The proof is syntactic; no exception interpretation is used.

Exercise 23.13.

The elementwise smart constructor is once(t):=[A,λ_.t,Var]. Packing gives the canonical body pack[A,λ_.t,Var]=(23.13)λ_.TVar(t):1T(TA). Thus the nested node is Scope(Once(TVar(t))), exactly the source’s fmapreturn construction.

After substitution by f:ATB, the elementwise node is [A,λ_.t,f]. Reindex it along f:ATB, with final continuation idTB, to obtain [TB,λ_.Tf(t),idTB]. For a general canonical scope whose body is u:T(TA), the same reindexing uses the function bf:TATB, bf(v)=v=f, and yields body Tbf(u). Applying the scoped functor therefore gives Scope(v)=f=(23.18)Scope(Γ(Tbf)(v)), which is (23.18). The first canonicalization uses functorial renaming TVar; the second uses reindexing (23.12) followed by the functor action Tbf.

Exercise 23.14.

Let τZ:HZTZ be the assumed sortwise translation. Put ψ^L:=τN(ψL):TN,ψ^R:=τ2(ψR):T2, and translate the continuation pointwise by κ^(r):=τA(κ(r)):TA. With X:=N+2, functorial renaming gives Tinl(ψ^L):TX,Tinr(ψ^R):TX. Thus differing fork-result types alone are not an obstruction.

Suppose first that ρ:XR is supplied. For every set Y, define ΦY():=ρ(:RY). For u:YZ, associativity of composition gives uΦY()=translationdefinitionu(ρ)=associativity(u)ρ=translationdefinitionΦZ(u), so the family is natural in Y.

Conversely, suppose Φ is natural, and define ρ:=ΦR(idR):XR. For any :RY, naturality with post-map :RY gives ρ=adapterdefinitionΦR(idR)=naturalityΦY(idR)=identity lawΦY(). Thus every natural family is precomposition by the recovered adapter. The two constructions are inverse by the same equations.

Now take R=. The carrier X=N+2 is inhabited by inl(0). If ρ:X existed, then ρ(inl(0)) would be an element of the empty set, a contradiction. Hence the fork can be homogenized, but its continuation domain cannot be structurally converted to the scoped carrier.

For the restricted positive case, take R=X and ρ=idX. Then ΦY()=translationdefinitionidX=identity law, so the continuation already has the scoped domain. For a scoped symbol with the two fork positions and a matching parameter p:Ps, the complete translated node is Scopes(p;X;(Tinl(ψ^L),Tinr(ψ^R));κ^). The response identification, equivalently the adapter ρ:XR, is additional operation-specific signature data. An arbitrary higher-order signature does not contain it, so this conditional bridge is not an equality or a general inclusion of the two calculi.

Search the book

Type to search the local edition.