Lectures onType Theory
Duplicate-label effect rows and inferred handlers
appendix sectionrules

Duplicate-label effect rows and inferred handlers

The exact signature of chapter 25 is τ::=αbτετ,ε::=με,σ::=α¯μ¯.τ,χ::=α¯μ¯.(τ!ε),v::=xcλx.e,e::=return vvve to x.eperform  vhandle e with Hlet x=e in e,H::={return xer; i(pi;ki)ei}i=1n. The handled labels are distinct. The fixed finite signature satisfies Σ()=PR, with every P,R closed and well kinded. Constants have a fixed signature C(c)=α¯μ¯.A whose declarations are closed and well kinded. Row equality is the least congruence generated by 1,2ε2,1ε. It has no contraction equation. Substitutions preserve the type and row kinds. Computation and value generalization are genc(Γ,A!ε)=(ftv(A!ε)ftv(Γ)).(A!ε),genv(Γ,A)=(ftv(A)ftv(Γ)).A.

The value and computation judgments are generated by the following complete rules; constants have their declared closed schemes and variable instantiation is kind preserving.

x:α¯μ¯.AΓT instantiates exactly α¯,μ¯
Γvx:TA
V-Var
C(c)=α¯μ¯.AT instantiates exactly α¯,μ¯
Γvc:TA
V-Const
Γ,x:Ae:B!ε
Γvλx.e:AεB
V-Lam
Γvv:A
Γreturn v:A!ε
C-Return
Γvv1:AεBΓvv2:A
Γv1v2:B!ε
C-App
Γe1:A!εΓ,x:Ae2:B!ε
Γe1 to x.e2:B!ε
C-To
Σ()=PRΓvv:P
Γperform  v:R!ε
C-Op
Γe1:A!a¯=ftv(A)ftv(Γ)Γ,x:a¯.Ae2:B!ε
Γlet x=e1 in e2:B!ε
C-Let
Γe:A!εεε
Γe:A!ε
C-RowConv
Γe:A!1,,nεΓ,x:Aer:B!ε(Σ(i)=PiRi)i=1n(Γ,pi:Pi,ki:RiεBei:B!ε)i=1n
Γhandle e with H:B!ε
C-Handle

Rows in common premises may be replaced by equivalent rows.

Evaluation and handler-free request contexts are E::=[]E to x.elet x=E in ehandle E with H,R::=[]R to x.elet x=R in e. Reduction is closed under E. Its complete roots are (λx.e)v0e[v/x],Beta(return v) to x.e0e[v/x],Tolet x=return v in e0e[v/x],Lethandle (return v) with H0er[v/x],HReturn. For the nearest syntactic handler, whose body context R contains no handler frame, handle R[perform i v] with H0ei[v/pi,(λy.handle R[return y] with H)/ki],HOp,handle R[perform  v] with H0perform  v to y.handle R[return y] with H,HForward, where the first rule requires ihandled(H) and the second requires handled(H). These tests are complementary; forwarding crosses exactly one handler layer.

Row exposure is the partial operation rewrite(ε,)=(S,ε) defined by rewrite(ε,)=(id,ε)RwHeadrewrite(ε,)=(S,ε)RwSkip,rewrite(ε,)=(S,ε),rewrite(μ,)=([μν],ν)RwVar, with fresh ν; rewriting fails. It satisfies SεSε. The complete unifier first applies reflexivity and variable binding, then uses U(a,a)=idUReflU(a,X)=[aX]UVar,aftv(X), aXU(X,a)=U(a,X)USym,X is not a variableU(b,b)=idUBaseU(,)=idUEmpty. The same-kind clash cases, tried after reflexivity and variables, are U(b,b)=failUClashBase,bbU(b,AεB)=failUClashBaseArrowU(AεB,b)=failUClashArrowBaseU(,ε)=failUClashEmptyExtendU(ε,)=failUClashExtendEmpty. A type–row equation is rejected as ill kinded before unification; U-Var fails its occurs check. Arrows solve domain, effect, then codomain: S1=U(A1,A2),S2=U(S1ε1,S1ε2),S3=U(S2S1B1,S2S1B2),U(A1ε1B1,A2ε2B2)=S3S2S1. For U(ε1,ε2) expose (S1,ε3) on the right, reject when tail(ε1)dom(S1), solve S2=U(S1ε1,S1ε3), and return S2S1.

Inference reports Wv(Γ,v)=(S,A) and Wc(Γ,e)=(S,A,ε). Variables instantiate every quantifier. If C(c)=α¯μ¯.A, the constant case replaces the displayed quantifiers by fresh variables through T, and returns (id,TA). A lambda infers its body under a fresh monotype. The computation clauses are, in source order:

  1. return a value and a fresh row variable;

  2. infer both application values and unify the operator with Aμα;

  3. infer both sides of sequencing and unify their effects;

  4. infer an operation parameter, unify it with P, and return R!μ;

  5. infer a let-bound computation, unify its effect with , generalize its value type, and infer the body;

  6. for a handler, infer the body as (S0,A0,ε0), choose fresh β,μ, and accumulate substitutions through the return clause and every operation clause. Each clause result is unified first with β and then with μ; clause i is inferred under pi:Pi and ki:Riμβ. Finally unify ε0 with 1,,nμ and report β!μ after the accumulated substitution.

Here is the exact handler accumulator. For a current substitution Q, put R=U(QX,QY),solve(Q;XY)=RQ. Choose fresh β,μ, compute (S0,A0,ε0)=Wc(Γ,e), and set Q0=S0. Infer the return clause and compose its local substitution before solving its two outputs: (Sr,Br,δr)=Wc(Q0Γ,x:Q0A0,er),Qr0=SrQ0,Qr1=solve(Qr0;Brβ),Qr=solve(Qr1;δrμ). Starting with Q0c=Qr, process operation clauses in source order: (Si,Bi,δi)=Wc(Qi1cΓ,pi:Pi,ki:RiQi1cμQi1cβ ; ei),Qi0=SiQi1c,Qi1=solve(Qi0;Biβ),Qic=solve(Qi1;δiμ). Finally set Q=solve(Qnc;ε01,,nμ) and return (Q,Qβ,Qμ). Every recursive inference call receives the environment after the current substitution; every displayed result is likewise fully substituted.

Generalized-evidence and exclusion cards

The generalized-evidence source and intermediate use ε::=εαeff,e::=veeeσprompt m h eyield m v,q::=(m,h,w),w::=:qw. Evidence extension and selection satisfy :qw.=q,:qw.=w.(). A prompt evaluates its body under :(m,h,w)w. An operation for label selects w.=(m,h,w), selects its clause from h, and yields to m. Only internal-safe terms generated from source terms may contain prompt, yield, or markers.

The monadic target has ordinary higher-kinded polymorphic lambda terms and Mon ε A=Evv εCtl ε A. The translation judgment is Γe:σεe. Its representative clauses are vgep=λw:Evv ε.Pure ε σgep vgep,v,e1e2gep=e1gep(λf.e2gepf),perform opgep=perform(select op). Here is the target control-monad bind: eg runs e under the current evidence vector, passes a Pure result to g, and extends the resumption of a Yield. The omitted type parameters are the explicit source annotations shown in Figure 5 and Figure 11 (Appendix E, “Full rules”) of the version-4 report [XL21]; this card does not reconstruct them by inference.

For effect exclusion, fix a finite universe U and Boolean effect formulas φ::=β{F}φcφφφφ. The source uses a T-prefix; this appendix renames it to Ex to avoid collision with the adjacent tunnelling and System-Xi cards. The local runtime interface is WF:=[] without F,Lx,e:=let x=[] in e,k::=WF::kLx,e::k,forb()=,forb(WF::k)={F}forb(k),forb(Lx,e::k)=forb(k). Configurations are ek; τkkφ types a stack and mek ok types a configuration. The characteristic typing, stack, and machine rules are

Γe:τφφ{F}B
Γe without F:τφ
Ex-Without
τkkφ
τk([] without F)::k(φ{F})
Ex-Forbid
e:τφ1τkkφ2φ1φ2B
mek ok
Ex-Machine

The machine step for do F(v) has the side condition Fforb(k). Pushing a without F expression creates the displayed forbid frame; a returned value pops it. There is no subeffecting rule.

Search the book

Type to search the local edition.