effect handlers, evidently - informatics research profile page · effect handlers, evidently...
TRANSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Effect Handlers, Evidently
NINGNING XIE,Microsoft Research, USA
JONATHAN IMMANUEL BRACHTHÄUSER, University of Tübingen, Germany
DANIEL HILLERSTRÖM, The University of Edinburgh, United Kingdom
PHILIPP SCHUSTER, University of Tübingen, Germany
DAAN LEIJEN,Microsoft Research, USA
Algebraic effect handlers are a powerful way to incorporate effects in a programming language. Sometimes
perhaps even too powerful. In this article we define a restriction of general effect handlers with scopedresumptions. We argue one can still express all important effects, while improving local reasoning about effect
handlers. Using the newly gained guarantees, we define a sound and coherent evidence translation for effect
handlers which directly passes the handlers as evidence to each operation. We prove full soundness and
coherence of the translation into plain lambda calculus. The evidence in turn enables efficient implementations
of effect operations; in particular, we showwe can execute tail-resumptive operations in place (without needingto capture the evaluation context), and how we can replace the runtime search for a handler by indexing with
a constant offset.
1 INTRODUCTIONAlgebraic effects [Plotkin and Power 2003] and the extension with handlers [Plotkin and Pret-
nar 2013], are a powerful way to incorporate effects in programming languages. Algebraic effect
handlers can express any free monad in a concise and composable way, and can be used to express
complex control-flow, like exceptions, asynchronous I/O, local state, backtracking, and much more.
Even though there are many language implementations of algebraic effects, like Koka [Lei-
jen 2014], Eff [Pretnar 2015], Frank [Lindley et al. 2017], Links [Lindley and Cheney 2012], and
Multicore OCaml [Dolan et al. 2015], the implementations may not be as efficient as one might
hope. Generally, handling effect operations requires a linear search at runtime to the innermost
handler. This is a consequence of the core operational rule for algebraic effect handlers:
handlem h E[perform op v] −→ f v k
requiring that (op→ f ) is in the handler h and that op is not in the bound operations in the
evaluation context E (so the innermost handler gets to handle the operation). The operation clause
f gets passed the operation argument v and the resumption k = λx . handlem h E[x]. Inspectingthis rule, we can see that implementations need to search through the evaluation context to find
the innermost handler, capture the context up to that point as the resumption, and can only then
invoke the actual operation clause f . This search often is linear in the size of the stack, or in the
number of intermediate handlers in the context E.In prior work, it has been shown that the vast majority of operations can be implemented much
more efficiently, often in time constant in the stack size. Doing so, however, requires an intricate
runtime system [Dolan et al. 2015; Leijen 2017a] or explicitly passing handler implementations,
instead of dynamically searching for them [Brachthäuser et al. 2018; Schuster et al. 2019; Zhang and
Myers 2019]. While the latter appears to be an attractive alternative to implement effect handlers,
a correspondence between handler passing and dynamic handler search has not been formally
established in the literature.
In this article, we make this necessary connection and thereby open up the way to efficient
compilation of effect handlers. We identify a simple restriction of general effect handlers, called
scoped resumptions, and we show that under this restriction we can perform a sound and coherent
evidence translation for effect handlers. In particular:
1
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
• The ability of effect handlers to capture resumptions k as a first-class value is very powerful
– perhaps too powerful as it can interfere with the ability to do local reasoning. We define the
notion of scoped resumptions (Section 2.2) as a restriction of general effect handlers where
resumptions can only be applied under the scope of their original handler context. We believe
all reasonable effect handlers can be written with scoped resumptions, while at the same
time ruling out many “wild” applications that have non-intuitive semantics. In particular, it
no longer allows handlers that change semantics of other operations than the ones it handles
itself. This improves the ability to use local reasoning over effects, and the coherence of
evidence translation turns out to only be preserved under scoped resumptions (more precisely:
an evidence translated program does not get stuck if resumptions are scoped). In this paper,
we focus on the evidence translation and use a dynamic check in our formalism. We show
various designs on how to check this property statically, but leave full exploration of such a
check to future work.
• To open up the way to more efficient implementations, we define a type directed evidencetranslation (Section 4) where the handlers are passed down as an implicit parameter to all oper-
ation invocations; similar to the dictionary translation in Haskell for type classes [Jones 1992],
or capability passing in Effekt [Brachthäuser et al. 2020]. This turns out to be surprisingly
tricky to get right, and we describe various pitfalls in Section 4.2. We prove that our transla-
tion is sound (Theorem 4 and 7) and coherent (Theorem 8), and that the evidence provided
at runtime indeed always corresponds exactly to the dynamic innermost handler in the
evaluation context (Theorem 5). In particular, on an evaluation step:
handlem h E[perform op ev v] −→ f v k with op ̸∈ bop(E) ∧ (op→ f ) ∈ h
the provided evidence ev will be exactly the pair (m, h), uniquely identifying the actual
(dynamic) handler m and its implementation h. This is the essence to enabling further
optimizations for efficient algebraic effect handlers.
Building on the coherent evidence translation, we describe various techniques for more efficient
implementations (Section 6):
• In practice, the majority of effects is tail resumptive, that is, their operation clauses have
the form op→ λx .λk. k e with k ̸∈ e. That is, they always resume once in the end with the
operation result. We can execute such tail resumptive operation clauses in place, e.g.
perform op (m, h) v −→ f v (λx . x) (optail→ f ) ∈ h
This is of course an important optimization that enables truly efficient effect operations at
a cost similar to a virtual method call (since we can implement handlers h as a vector of
function pointers where op is at a constant offset such that f = h.op).• Generally, evidence is passed as an evidence vector w where each element is the evidence for
a specific effect. That means we still need to select the right evidence at run-time which can
be a linear time operation (much like the dynamic search for the innermost handler in the
evaluation context). We show that by keeping the evidence vectors in canonical form, we
can index the evidence in the vector at a constant offset for any context where the effect is
non-polymorphic.
• Since the evidence provides the handler implementation directly, it is no longer needed in the
context. We can follow Brachthäuser and Schuster [2017] and use an implementation based
2
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
on multi-prompt delimited continuations [Dyvbig et al. 2007; Gunter et al. 1995] instead.
Given evidence (m, h), we directly yield to a specific prompt m:
handlem h E[perform op (m, h) v]⇝promptm E[yieldm (λk. (h.op) v k)]
We define a monadic multi-prompt translation (Section 5) from an evidence translated pro-
gram (in Fev) into standard call-by-value polymorphic lambda calculus (Fv) where the monad
implements the multi-prompt semantics, and we prove that this monadic translation is sound
(Theorem 10) and coherent (Theorem 11). Such translation is very important, as it provides
the missing link between traditional implementations based on dynamic search for the
handler [Dolan et al. 2015; Leijen 2014; Lindley et al. 2017] and implementations of lexical
effect handlers using multi-prompt delimited control [Biernacki et al. 2019; Brachthäuser
and Schuster 2017; Zhang and Myers 2019]. It also means we can use a standard compilation
backend where all usual optimizations apply that would not hold under algebraic effect
semantics directly (since all effects become explicit now). For example, as all handlers be-
come regular data types, and evidence is a regular parameter, standard optimizations like
inlining can often completely inline the operation clauses at the call site without any special
optimization rules for effect handlers [Pretnar et al. 2017]. Moreover, no special runtime
system for capturing the evaluation context is needed anymore, like split-stacks [Dolan et
al. 2015] or stack copying [Leijen 2017a], and we can generate code directly for any host
platform (including C or WebAssembly). In particular, recent advances in compilation guided
reference counting [Ullrich and Moura 2019] can readily be used. Such reference counting
transformations cannot be applied to traditional effect handler semantics since any effect
operation may not resume (or resume more than once), making it impossible to track the
reference counts directly.
We start by giving an overview of algebraic effects and handlers and their semantics in an untyped
calculus λϵ (Section 2), followed by a typed polymorphic formalization Fϵ (Section 3) for which we
prove various theorems like soundness, preservation, and the meaning of effect types. In Section 4
we define an extension of Fϵ with explicit evidence vector parameters, called Fev , define a formal
evidence passing translation, and prove this translation is coherent and preserves the original
semantics. Using the evidence translated programs, we define a coherent monadic translation
in Section 5 (based on standard multi-prompt semantics) that translates into standard call-by-
value polymorphic lambda-calculus (called Fv). Section 6 discusses various immediate optimization
techniques enabled by evidence passing, in particular tail-resumption optimization, effect-selective
monadic translation, and bind-inlining to avoid explicit allocation of continuations.
For space reasons, we put all evaluation context type rules and the full proofs of all stated lemmas
and theorems in the supplemental Appendix which also includes further discussion of possible
extensions.
2 UNTYPED ALGEBRAIC EFFECT HANDLERSWe begin by formalizing a minimal calculus of untyped algebraic effect handlers, called λϵ . Theformalization helps introduce the background, sets up the notations used throughout the paper,
and enables us to discuss examples in a more formal way.
The formalization of λϵ is given in Figure 1. It is essentially standard call-by-value lambda calculus
extended with a rule to perform operations and a rule to handle them. It corresponds closely to
the untyped semantics of Forster et al. [2019], and the effect calculus presented by Leijen [2017c].
Sometimes, effect handler semantics are given in a form that does not use evaluation contexts, e.g.
3
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
Expressions
e ::= v (value)
| e e (application)
| handle h e (handler instance)
Values
v ::= x (variables)
| λx . e (functions f )| handler h (effect handler)
| perform op (operation)
Handlers h ::= {op1→ f1, . . ., opn→ fn } (operation clauses)
Evaluation Context F ::= □ | F e | v F (pure evaluation)
E ::= □ | E e | v E | handle h E (effectful computation)
(app) (λx . e) v −→ e[x:=v](handler) (handler h) v −→ handle h · v ()(return) handle h · v −→ v(perform) handle h · E · perform op v −→ f v k iff op ̸∈ bop(E) ∧ (op→ f ) ∈ h
where k = λx . (handle h · E · x)
e −→ e′
E · e 7−→ E · e′[step]
bop(□) = ∅bop(E e) = bop(E)bop(v E) = bop(E)bop(handle h E)= bop(E) ∪ { op | (op→ f ) ∈ h }
Fig. 1. λϵ : Untyped Algebraic Effect Handlers
[Kammar and Pretnar 2017; Pretnar 2015], but in the end both formulations are equivalent (except
that using evaluation contexts turns out to be convenient for our proofs).
There are two differences to earlier calculi: we leave out return clauses (for simplicity) and instead
of one handle h expression we distinguish between handle h e (as an expression) and handler h(as a value). A handler h v evaluates to handle h (v ()) and just invokes its given function v with
a unit value under a handle h frame. As we will see later, handler is generative and instantiates
handle frames with a unique marker. As such, we treat handle as a strictly internal frame that only
occurs during evaluation.
The evaluation contexts consist of pure evaluation contexts F and effectful evaluation contexts Ethat include handle h E frames. We assume a set of operation names op. The perform op v constructcalls an effect operation op by passing it a value v. Operations are handled by handle h e expressions,which can be seen in the (perform) rule. Here, the condition op ̸∈ bop(E) ensures that the innermosthandle frame handles an operation. To evaluate an operation call, evaluation continues with the
body of the operation clause (op→ f ), passing the argument value v and the resumption k to f .Note that f v k is not evaluated under the handler h, while the resumption always resumes under
the handler h again; this describes the semantics of deep handlers and correspond to a fold in a
categorical sense (as opposed to shallow handlers that are more like a case) [Kammar et al. 2013].
For conciseness, we often use the dot notation to decompose and compose evaluation contexts,
which also conveys more clearly that an evaluation context essentially corresponds to a runtime
stack. For example, we would write v · handle h · E · e as a shorthand for v (handle h (E[e])). Thedot notation can be defined as:
E · e � E[e]□ e · E� E e
v □ · E � v · E � v Ehandle h □ · E � handle h · E � handle h E
4
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
2.1 ExamplesHere are some examples of common effect handlers. Almost all practical uses of effect handlers are
a variation of these.
Exceptions: Assuming we have data constructors just and nothing, we can define a handler for
exceptions that converts any exceptional computation e to either just v on success, or nothing on
an exception:
handler { throw→ λx . λk. nothing } (λ_. just e)For example using e = perform throw () evaluates to nothing while e = 1 evaluates to just 1.
Reader: In the exception example we just ignored the argument and the resumption of the
operation but the reader effect uses the resumption to resume with a result:
handler { get → λx . λk. k 1 } (λ_. perform get () + perform get ())Here we handle the get operation to always return 1 so the evaluation proceeds as:
handler { get → λx . λk. k 1 } (λ_. perform get () + perform get ())7−→∗ handle h · perform get () + perform get ()7−→∗ (λx . handle h · (□ + perform get ()) · x) 1
7−→ handle h · (□ + perform get ()) · 17−→∗ handle h · (1 + □) · 17−→∗ 2
State: The state effect is more involved with pure effect handlers as we need to return functions
from the operation clauses (essentially as a state monad) (variant 1):h = { get → λx . λk. (λy. k y y), set → λx . λk. (λy. k () x) }(handler h (λ_. (perform set 21; x ← perform get (); (λy. x + x))) 0
where we assume x ← e1; e2 as a shorthand for (λx . e2) e1, and e1; e2 for (_← e1; e2).
The evaluation of an operation clause now always return directly with a function that takes the
current state as its input; which is then used to resume with:
(handler h (λ_. perform set 21; x ← perform get (); (λy. y + x) )) 0
7−→∗ (□ 0) · handle h · (□; x ← perform get (); (λy. x + x)) · perform set 21
7−→∗ (□ 0) · (λy. k () 21) with k = λx . handle h · (□; x ← perform get (); (λy. y + x)) · x= (λy. k () 21) 0
7−→ k () 21
7−→ (handle h · (□; perform get ()) · ()) 21
= (□ 21) · handle h · (() ; perform get ())7−→ 42
Clearly, defining local state as a function is quite cumbersome, so usually one allows for parame-terized handlers [Leijen 2016; Plotkin and Pretnar 2013] that keep a local parameter p with their
handle frame, where the evaluation rules become:
phandler h v ′ v −→ phandle h v ′ · v ()phandle h v ′ · E · perform op v −→ f v ′ v k iff op ̸∈ bop(E) ∧ (op→ f ) ∈ h
where k = λy x . (handle h y · E · x). Here the handler parameter v ′ is passed to the operation
clause f and later restored in the resumption which now takes a fresh parameter y besides the
result value x. With a parameterized handler the state effect can be concisely defined as (variant 2):h = { get → λy x k. k y y, set → λy x k. k x () }phandler h 0 (λ_. perform set 21; x ← perform get (); x + x)
Another important advantage in this implementation is that the state effect is now tail resumptivewhich is very beneficial for performance (as shown in the introduction).
5
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
There as yet another elegant way to implement local state by Biernacki et al. [2017], where the
get and set operations are defined in separate handlers (variant 3):
h = { set → λx k. handler { get → λ_ k. k x } (λ_. k ()) }handler h (λ_. perform set 42; x ← perform get (); x + x)
The trick here is that every set operation installs a fresh handler for the get operation and resumes
under that (so the innermost get handler always contains the latest state). Even though elegant,
there are some drawbacks to this encoding: a naive implementation may use n handler frames for
n set operations, typing this example is tricky and usually requires masking [Biernacki et al. 2017;
Hillerström and Lindley 2016], and, as we will see, it does not use scoped resumptions and thus
cannot be used with evidence translation.
Backtracking: By resuming more than once, we can implement backtracking using algebraic
effects. For example, the amb effect handler collects all all possible results in a list by resuming the
flip operation first with a true result, and later again with a false result:
handler { flip→ λ_ k. xs← k true; ys← k false; xs ++ ys }(λ_. x ← perform flip (); y← perform flip (); [x && y])
returning the list [false, false, false, true] in our example. This technique can also be used for
probabilistic programming [Kiselyov and Shan 2009].
Async: We can use resumptions k as first class values and for example store them into a queue to
implement cooperative threads [Dolan et al. 2017] or asynchronous I/O [Leijen 2017b]. Assuming
we have a state handler hqueue that maintains a queue of pending resumptions, we can implement a
mini-scheduler as:
hasync = { fork → λf k. perform enqueue k; schedule f ()yield→ λ_ k. perform enqueue k; k′← perform dequeue (); k′ () }
where enqueue enqueues a resumption k, and dequeue () resumes one, or returns unit () if the queue
is empty. The schedule function runs a new action f under the scheduler handler:
schedule= λf _. handler hasync (λ_. f (); perform dequeue ())async = λf . handler hqueue (λ_. schedule f ())
The main wrapper async schedules an action under a fresh scheduler queue handler hqueue , whichis shared by all forked actions under it.
2.2 Scoped ResumptionsThe ability of effect handlers to capture the resumption as a first-class value is very powerful –
and can be considered as perhaps too powerful. In particular, it can be (ab)used to define handlers
that change the semantics of other handlers that were defined and instantiated orthogonally. Take
for example an operation op1that is expected to always return the same result, say 1. We can now
define another operation opevil that changes the return value of op1after it is invoked! Consider
the following program where we leave f and hevil undefined for now:
h1 = { op1→ λx k. k 1 }
e = perform op1(); perform opevil (); perform op
1()
f (handler h1 (λ_. handler hevil (λ_. e)))
6
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
Even though h1 is defined as a pure reader effect and defined orthogonal to any other effect, the
opevil operation can still cause the second invocation of op1to return 2 instead of 1! In particular,
we can define f and hevil as 1:
h2 = { op1→ λx k. k 2 }
hevil = { opevil → λx k. k }f = λk. handler h2 (λ_. k ())
The trick is that the handler hevil does not directly resume but instead returns the resumption k asis, after unwinding through h1 it is passed to f which now invokes the resumption k under a fresh
handler h2 for op1causing all subsequent op
1operations to be handled by h2 instead.
We consider this behavior undesirable in practice as it limits the ability to do local reasoning.
In particular, a programmer may not expect that calling opevil changes the semantics of op1. Yet
there is no way to forbid it. Moreover, it also affects static analysis and it turns out for example
that efficient evidence translation (with its subsequent performance benefits) is not possible if we
allow resumptions to be this dynamic.
The solution we propose in this paper is to limit resumptions to be scoped only: that is, aresumption can only be applied under the same handler context as it was captured. The handler contextis the evaluation context where we just consider the handler frames, e.g. for any evaluation context Eof the form F0 · handle h1 · F1 · . . . · handle hn · Fn, the handler context, hctx(E), is h1 · h2 · . . . · hn.In particular, the evil example is rejected as it does not use a scoped resumption: k is captured
under h1 but applied under h2.
Our definition of scoped resumption is minimal in the sense that it is the minimal requirement
needed in the proofs to maintain coherence of evidence translation. In this paper, we guarantee
scoped resumptions using a dynamic runtime check in evidence translated programs (called guard),but it is also possible to check it statically. It is beyond the scope of this paper to give a particular
design, but some ways of doing this are:
• Lexical scoping: a straightforward approach is to syntactically restrict the use of the resump-
tion to be always in the lexical scope of the handler: i.e. fully applied within the operation
clause and no occurrences under a lambda (so it cannot escape or be applied in nested handler).
This can perhaps already cover all reasonable effects in practice, especially in combination
with parameterized handlers2.
• A more sophisticated solution could use generative types for handler names, together with a
check that those types do not escape the lexical scope as described by Zhang andMyers [2019]
and also used by Biernacki et al. [2019] and Brachthäuser et al. [2020]. Another option could
be to use rank-2 types to prevent the resumption from escaping the lexical scope in which
the handler is defined [Leijen 2014; Peyton Jones and Launchbury 1995].
It turns out that the seminal work on algebraic effect handlers by Plotkin and Pretnar [2013] also
used a similar restriction as scoped resumptions, and as such, we believe that scoped resumptions
are closer to the original categorical interpretation of effect handlers. Plotkin and Pretnar use the
first technique to syntactically restrict the use of resumptions under the scope of the operation
clause. Resumptions variables k are in a separate syntactic class, always fully applied, and checked
under a context K separate from Γ. However, they still allow occurrences under a lambda, allowing
a resumption to escape, although in that case the evaluation would no longer type check (i.e. there is
no preservation of typings under evaluation). As such it is not quite the same as scoped resumptions:
1Note that this example is fine in λϵ but cannot be typed in Fϵ as is – we discuss a properly typed version in Section 4.5.
2The lexical approach could potentially be combined with an “unsafe” resumption that uses a runtime check as done this
article to cover any remaining situations.
7
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
Expressions
e ::= v (value)
| e e (application)
| e[σ ] (type application)
| handle h e (handler instance)
Values
v ::= x (variables)
| λϵx :σ . e (abstraction)
| Λαk . v (type abstraction)
| handlerϵ h (effect handler)
| performϵ op σ (operation)
Handlers h ::= {op1→ f1, . . ., opn→ fn }
Evaluation Context F ::= □ | F e | v F | F [σ ]E ::= □ | E e | v E | E [σ ] | handleϵ h E
(app) (λϵx :σ . e) v −→ e[x:=v](tapp) (Λαk . v) [σ ] −→ v[α :=σ ](handler) (handlerϵ h) v −→ handleϵ h · v ()(return) handleϵ h · v −→ v(perform) handleϵ h · E · perform op σ v −→ f [σ ] v k iff op ̸∈ bop(E) ∧ (op→ f ) ∈ h
where op : ∀α . σ1→ σ2 ∈ Σ(l)k = λϵx :σ2[α :=σ ]. handleϵ h · E · x
Fig. 2. System Fϵ : explicitly typed algebraic effect handlers. Figure 3 defines the types.
it is both more restrictive as it needs k to occur fully applied under an operation clause; but also
more liberal as it allows the separate handler state example (since k can occur under a lambda).
2.3 ExpressivenessScoped resumptions bring easier-to-reason control flow, and, as we will see, open up new design
space for algebraic effects compilation. However, one might worry about the expressiveness of
scoped resumptions. We believe that all important effect handlers in practice can be defined in
terms of scoped resumptions. In particular, note that it is still allowed for a handler to grow its
context with applicative forms, for example:
handler { tick→ λx k. 1 + k () } (λ_. tick (); tick (); 1)
evaluates to 3 by keeping (1 + □) frames above the resumption. In this example, even though the
full context has grown, k is still a scoped resumption as it resumes under the same (empty) handler
context. Similarly, the async scheduler example that stores resumptions in a stateful queue is also
accepted since each resumption still resumes under the same handler context (with the state queue
handler on top). Multiple resumptions as in the backtracking example are also fine.
There are two main exceptions we know of. First, the state variant 3 based on two separate
handlers does not use scoped resumptions since the set resumption resumes always under a handler
context extended with a get handler. However, we can always use, and due to the reasons we have
mentioned we may actually prefer, the normal state effect or the parameterized state effect. Second,
shallow handlers do not resume under their own handler and as a result generally resume under a
different handler context than they captured. Fortunately, any program with shallow handler can
be expressed with deep handlers as well [Hillerström and Lindley 2018; Kammar et al. 2013] and
thus avoid the unscoped resumptions.
3 EXPLICITLY TYPED EFFECT HANDLERS IN SYSTEM Fϵ
8
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
Types
σ ::= αk(type variables of kind k)
| ck σ . . . σ (type constructor of kind k)| σ → ϵ σ (function type)
| ∀αk . σ (quantified type)
Kinds
k ::= ∗ (value type)
| k→ k (type constructors)
| eff (effect type (µ,ϵ))| lab (basic effect (l))
Effect signature sig ::= { op1
: ∀α1. σ1→ σ ′1, . . ., opn : ∀αn. σn→ σ ′n}
Effect signatures Σ ::= {l1 : sig1, . . ., ln : sign }
Type Constructors ⟨⟩ : eff empty effect row (total)
⟨_ | _⟩ : lab→ eff→ eff effect row extension
marker : eff→ ∗ → ∗ handler instance marker (m)
evv : eff→ ∗ evidence vector (w,z)ev : lab→ ∗ evidence (ev)_→ _ _ : ∗ → eff→ ∗ function arrow
Syntax ⟨l1, . . ., ln⟩ � ⟨l1 | . . . | ⟨ln | ⟨⟩⟩ . . . ⟩⟨l1, . . ., ln | µ⟩ � ⟨l1 | . . . | ⟨ln | µ⟩ . . . ⟩ϵ ::= σ eff
, µ ::= αeff, l ::= clab
Fig. 3. System Fϵ : types
ϵ ≡ ϵ[refl]
l1 , l2 ϵ1 ≡ ϵ2
⟨l1, l2 | ϵ1⟩ ≡ ⟨l2, l1 | ϵ2⟩[eq-swap]
ϵ1 ≡ ϵ2 ϵ2 ≡ ϵ3
ϵ1 ≡ ϵ3
[eq-trans]
ϵ1 ≡ ϵ2
⟨l | ϵ1⟩ ≡ ⟨l | ϵ2⟩[eq-head]
Fig. 4. Equivalence of row-types.
To prepare for a type directed evidence translation, we first define a typed version of the untyped
calculus λϵ called System Fϵ – a call-by-value effect handler calculus extended with (higher-rank
impredicative) polymorphic types and higher kinds à la System Fω , and row based effect types.
Figure 2 defines the extended syntax and evaluation rules with the syntax of types and kinds
in Figure 3. System Fϵ serves as an explicitly typed calculus that can be the target language of
compilers and, for this article, serves as the basis for type directed evidence translation.
Being explicitly typed, we now have type applications e[σ ] and abstractions Λαk . v. Also,λϵ x :σ .e, handleϵ h e, handlerϵ h, and performϵ op σ all carry an effect type ϵ . Effect types are(extensible) rows of effect labels l (like exn or state). In the types, every function arrow σ1→ ϵ σ2
takes three arguments: the input type σ1, the output type σ2, and its effects ϵ when it is evaluated.
Since we have effect rows, effect labels, and regular value types, we use a basic kind system to
keep them apart and to ensure well-formedness (⊢wf) of types (as defined in the Appendix).
3.1 Effect RowsAn effect row is either empty ⟨⟩ (the total effect), a type variable µ (of kind eff), or an extension
⟨l | ϵ⟩ where ϵ is extended with effect label l. We call effects that end in an empty effect closed, i.e.
9
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
⟨l1, . . ., ln⟩; and effects that end in a polymorphic tail open, i.e. ⟨l1, . . ., ln | µ⟩. Following Biernacki etal. [2017] and Leijen [2014], we use simple effect rows where labels can be duplicated, and where an
effect ⟨l, l ⟩ is not equal to ⟨l ⟩. We consider rows equivalent up to the order of the labels as defined in
Figure 4. There exists a complete and sound unification algorithm for these row types [Leijen 2005]
and thus these are also very suitable for Hindley-Milner style type inference.
We consider using simple row-types with duplicate labels a suitable choice for a core calculus
since it extends System F typing seamlessly as we only extend the notion of equality between
types. There are other approaches to typing effects but all existing approaches depart from standard
System F typing in significant ways. Row typing without duplicate labels leads to the introduction
of type constraints, as in T-REX for example [Gaster and Jones 1996], or kinds with presence
variables (Rémy style rows) as in Links for example [Hillerström and Lindley 2016; Rémy 1994].
Another approach is using effect subtyping [Bauer and Pretnar 2014] but that requires a subtype
relation between types instead of simple equality.
The reason we need equivalence between row types up to order of effect labels is due to poly-
morphism. Suppose we have two functions that each use different effects:
f1 : ∀µ . () → ⟨l1 | µ⟩ () f2 : ∀µ . () → ⟨l2 | µ⟩ ()We would still like to be able to express choose f1 f2 where choose : ∀α . α → α → α . Using row
types we can type this naturally as:
Λµ . choose[() → ⟨l1, l2 | µ⟩ ()] (f1[⟨l2 | µ⟩]) (f2[⟨l1 | µ⟩])
where the types of the arguments are now equivalent ⟨l1 | ⟨l2 | µ⟩⟩ ≡ ⟨l2 | ⟨l1 | µ⟩⟩ (without needingsubtype constraints or polymorphic label flags).
Similarly, duplicate labels can easily arise due to type instantiation. For example, a catch handler
for exceptions can have type:
catch : ∀µ α . (() → ⟨exn | µ⟩ α) → (string→ µ α) → µ α
where catch takes an action that can raise exceptions, and a handler function that is called when
an exception is caught. Suppose though an exception handler raises itself an exception, and has
type h : ∀µ . string→ ⟨exn | µ⟩ int. The application catch action h is then explicitly typed as:
Λµ . catch[⟨exn | µ⟩, int] action h[µ]
where the type application gives rise to the type:
catch[⟨exn | µ⟩, int] : (() → ⟨exn, exn | µ⟩ int) → (string→ ⟨exn | µ⟩ int) → ⟨exn | µ⟩ int
naturally leading to duplicate labels in the type. As we will see, simple row types also correspond
naturally to the shape of the runtime evidence vectors that we introduce in Section 4.1 (where
duplicated labels correspond to nested handlers).
3.2 OperationsWe assume the every effect l has a unique set of operations op
1to opn with a signature sig that gives
every operation its input and output types, opi : ∀α i . σi → σ ′i . There is a global map Σ that maps
each effect l to its signature. Since we assume that each op is uniquely named, we use the notation
op : ∀α . σ1→ σ2 ∈ Σ(l) to denote the type of op that belongs to effect l, and also op ∈ Σ(l) tosignify that op is part of effect l.Note that we allow operations to be polymorphic. Therefore perform op σ v contains the in-
stantiation types σ which are passed to the operation clause f in the evaluation rule for (perform)(Figure 2). This means that operations can be used polymorphically, but the handling clause itself
must be polymorphic in the operation types (and use them as abstract types).
10
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
3.3 Quantification and Equivalence to the Untyped Dynamic SemanticsWe would like the property that if we do type erasure on the newly defined System Fϵ we have the
same semantics as with the untyped dynamic semantics, i.e.
Theorem 1. (System Fϵ has untyped dynamic semantics)If e1 −→ e2 in System Fϵ , then either e∗
1−→ e∗
2or e∗
1= e∗
2.
where e∗ stands for the term e with all types, type abstractions, and type applications removed.
This seem an obvious property but there is a subtle interaction with quantification. Suppose we
(wrongly) allow quantification over expressions instead of values, like Λα . e, then consider:
h = { tick→ λx : () k : (() → ⟨⟩ int). 1 + k () }handle h ((λx :∀α . int. x[int] + x[bool]) (Λα . tick (); 1))
In the typed semantics, this would evaluate the argument x at each instantiation (since the whole
Λα . tick (); 1 is passed as a value), resulting in 4. On the other hand, if we do type erasure, the
untyped dynamic semantics evaluates to 3 instead (evaluating the argument before applying). Not
only do we lose untyped dynamic semantics, but we also break parametricity (as we can observe
instantiations). So, it is quite important to only allow quantification over values, much like the ML
value restriction [Kammar and Pretnar 2017; Pitts 1998; Wright 1995]. In the proof of Theorem 1
we use in particular the following (seemingly obvious) Lemma:
Lemma 1. (Type erasure of values)If v is a value in System Fϵ then v∗ is a value in λϵ .
Not all systems in the literature adhere to this restriction; for example Biernacki et al. [2017]
and Leijen [2016] allow quantification over expressions as Λα . e, where both ensure soundness
of the effect type system by disallowing type abstraction over effectful expressions. However, we
believe that this remains a risky affair since Lemma 1 does not hold; and thus a typed evaluation
may take more reduction steps than the type-erased term, i.e. seemingly shared argument values
may be computed more than once.
3.4 Type Rules for System Fϵ
Figure 5 defines the typing rules for System Fϵ . The rules are of the form Γ ;w ⊢ e : σ | ϵ ⇝ e′
for expressions where the variable context Γ and the effect ϵ are given (↑), and σ is synthesized (↓).
The gray parts define the evidence translation which we describe in Section 4 and these can be
ignored for now. Values are not effectful, and are typed as Γ ⊢val v : σ ⇝ v ′ . Since the effects areinherited, the lambda needs an effect annotation that is passed to the body derivation (abs). In the
rule app we use standard equality between types and require that all effects match. The val rule
goes from a value to an expression (opposite of abs) and allows any inherited effect. The handler
rule takes an action with effect ⟨l | ϵ⟩ and handles l leaving effect ϵ . The handle rule is similar, but
is defined over an expression e and types e under an extended effect ⟨l | e⟩ in the premise.
In the Appendix, there are type rules for evaluation contexts where Γ ⊢ec E : σ1→ σ2 | ϵ signifiesthat a context E can be typed as a function from a term of typeσ1 toσ2 where the resulting expression
has effect ϵ . These rules are not needed to check programs but are very useful in proofs and theorems.
In particular,
Lemma 2. (Evaluation context typing)If ∅⊢ec E : σ1→ σ2 | ϵ and ∅ ⊢ e : σ1 | ⟨⌈E⌉l | ϵ⟩, then ∅ ⊢ E[e] : σ2 | ϵ .
where ⌈E⌉ l extracts all labels l from a context in reverse order:
⌈F0 · handle h1 · F1 · . . . · handle hn · Fn⌉ l = ⟨ln, . . ., l1⟩
11
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
Γ↑; w↑Fev
⊢ e↑Fϵ
: σ↓| ϵ↑⇝ e′
↓Fev
Γ↑⊢val v
↑Fϵ
: σ↓⇝ v ′
↓Fev
Γ↑⊢ops h
↑Fϵ
: σ↓| l↓| ϵ↑⇝ h′
↓Fev
x :σ ∈ Γ
Γ ⊢val x : σ ⇝ x[var]
Γ ⊢val v : σ ⇝ v ′
Γ ;w ⊢ v : σ | ϵ ⇝ v ′[val]
Γ ;w ⊢ e1 : σ1→ ϵ σ | ϵ ⇝ e′1
Γ ;w ⊢ e2 : σ1 | ϵ ⇝ e′2
Γ ;w ⊢ e1 e2 : σ | ϵ ⇝ e′1w e′
2
[app]
Γ, x :σ1 ; z ⊢ e : σ2 | ϵ ⇝ e′ fresh z
Γ ⊢val λϵ x :σ1. e : σ1→ϵ σ2 ⇝ λϵ z : evv ϵ, x : ⌈σ1⌉ . e′
[abs]
Γ ⊢val v : σ ⇝ v ′
Γ ⊢val Λαk . v : ∀αk . σ ⇝ Λαk . v ′[tabs]
Γ ;w ⊢ e : ∀αk . σ1 | ϵ ⇝ e′ ⊢wf σ : k
Γ ;w ⊢ e[σ ] : σ1[α :=σ ] | ϵ ⇝ e′[⌈σ ⌉][tapp]
op : ∀α . σ1→ σ2 ∈ Σ(l) α ̸∈ ftv(Γ)
Γ ⊢val performϵ op σ : σ1[α :=σ ] → ⟨l | ϵ⟩ σ2[α :=σ ] ⇝ performϵ op σ[perform]
opi : ∀α i . σ1→ σ2 ∈ Σ(l) α ̸∩ ftv(ϵ σ )Γ ⊢val fi : ∀α . σ1→ ϵ ((σ2→ ϵ σ ) → ϵ σ ) ⇝ f ′i
Γ ⊢ops { op1→ f1, . . ., opn→ fn } : σ | l | ϵ ⇝ { opi → f ′i }
[ops]
Γ ⊢ops h : σ | l | ϵ ⇝ h ′
Γ ⊢val handlerϵ h : (() → ⟨l | ϵ⟩ σ ) → ϵ σ ⇝ handlerϵ h′[handler]
Γ ⊢ops h : σ | l | ϵ ⇝ h′ Γ ; ⟨⟨l : (m, h′) | w⟩⟩ ⊢ e : σ | ⟨l | ϵ⟩ ⇝ e′
Γ ; w ⊢ handleϵ h e : σ | ϵ ⇝ handlewm h′ e′[handle]
Fig. 5. Type Rules for System Fϵ combined with type directed evidence translation to Fev (in gray.)
with li corresponding to each hi (for any op ∈ hi , op ∈ Σ(li)). The above lemma shows we can plug
well-typed expressions in a suitable context. The next lemma uses this to show the correspondence
between the dynamic evaluation context and the static effect type:
Lemma 3. (Effect corresponds to the evaluation context)If∅ ⊢ E[e] : σ | ϵ then there existsσ1 such that∅ ⊢ec E : σ1→ σ | ϵ , and∅ ⊢ e : σ1 | ⟨⌈E⌉l | ϵ⟩ .
Here we see that the rules guarantee that exactly the effects ⌈E⌉l in e are handled by the context E.
3.5 Progress and PreservationWe establish two essential lemmas about the meaning of effect types. First, in any well-typed total
System Fϵ expression, all operations are handled (and thus, evaluation cannot get stuck):
Lemma 4. (Well typed operations are handled)If ∅ ⊢ E[perform op σ v] : σ | ⟨⟩ then E has the form E1 · handleϵ h · E2 with op ̸∈ bop(E2) and
op→ f ∈ h.
Moreover, effect types are meaningful in the sense that an effect type fully reflects all possible
effects that may happen during evaluation:
12
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
Expressions
e ::= v (value)
| e[σ ] (type application)
| e w e (evidence application)
| handlewm h e (handler instance)
Values
v ::= x (variables)
| λϵ z : evv ϵ, x :σ . e (evidence abstraction)
| Λαk . v (type abstraction)
| handlerϵ h (effect handler)
| performϵ op σ (operation)
| guardw E σ (guarded abstraction)
(app) (λϵ z : evv ϵ, x :σ . e) w v −→ e[z:=w, x:=v](tapp) (Λαk . v) [σ ] −→ v[α :=σ ](handler) (handlerϵ h) w v −→ handlewm h (v ⟨⟨l : (m, h) | w⟩⟩ ())
where m is unique and h ∈ Σ(l)(return) handlewm h · v −→ v(perform) handlewm h · E · performϵ op σ w ′ v −→ f [σ ] w v w k iff op ̸∈ bop(E) ∧ (op→ f ) ∈ h
where op : ∀α . σ1→ σ2 ∈ Σ(l)k = guardw (handlewm h · E) (σ2[α :=σ ])
(guard) (guardw E σ ) w v −→ E[v]
Fig. 6. System Fev Typed operational semantics with evidence
Lemma 5. (Effects types are meaningful)If ∅ ⊢ E[perform op σ v] : σ | ϵ with op ̸∈ bop(E), then op ∈ Σ(l) and l ∈ ϵ , i.e. effect types can-not be discarded without a handler.
Using these Lemmas, we can show that evaluation can always make progress and that the typings
are preserved during evaluation.
Theorem 2. (Progress)If ∅ ⊢ e1 : σ | ⟨⟩ then either e1 is a value, or e1 7−→ e2.
Theorem 3. (Preservation)If ∅ ⊢ e1 : σ | ⟨⟩ and e1 7−→ e2, then ∅ ⊢ e2 : σ | ⟨⟩.
4 POLYMORPHIC EVIDENCE TRANSLATION TO SYSTEM Fev
Having established a sound explicitly typed core calculus, we can now proceed to do evidence
translation. The goal of evidence translation is to pass down evidence ev of the handlers in the
evaluation context to place where operations are performed. This will in turn enable other op-
timizations (as described in Section 6) since we can now locally inspect the evidence instead of
searching in the dynamic evaluation context.
Following Brachthäuser and Schuster [2017], we represent evidence ev for an effect l as a pair(m, h), consisting of a unique marker m and its corresponding handler implementation h. Themarkers uniquely identify each handler frame in the context which is nowmarked as handlem h. Thereason for introducing the separate handler h construct is now apparent: it instantiates handlem hframes with a uniquem. This representation of evidence allows for two important optimizations: (1)
We can change the operational rule for perform to directly yield to a particular handler identified
by m (instead of needing to search for the innermost one), shown in Section 5.1, and (2) It allows
local inspection of the actual handler h so we can evaluate tail resumptive operations in place,
shown in Section 6.
13
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
However, passing the evidence down to each operation turns out to be surprisingly tricky to get
right and we took quite a few detours before arriving at the current solution. At first, we thought
we could represent evidence for each label l in the effect of a function as separate argument evl .For example,
f1 : ∀µ . int → ⟨l1 | µ⟩ int = Λµ . λx . perform op1x
would be translated as:
f1 : ∀µ . ev l→ int → ⟨l1 | µ⟩ int = Λµ . λev. λx . perform op1ev x
This does not work though as type instantiation can now cause the runtime representation to
change as well! For example, if we instantiate µ to ⟨l2⟩ as f [⟨l2⟩] the type becomes int → ⟨l1, l2⟩ intwhich now takes two evidence parameters. Even worse, such instantiation can be inside arbitrary
types, like a list of such functions, where we cannot construct evidence transformers in general.
Another design that does not quite work is to regard evidence translation as an instance of
qualified types [Jones 1992] and use a dictionary passing translation. In essence, in the theory of
qualified types, the qualifiers are scoped over monomorphic types, which does not fit well with
effect handlers. Suppose we have a function foo with a qualified evidence types as:
foo : Ev l1⇒ (int → ⟨l1⟩ int) → ⟨l1⟩ intNote that even though foo is itself qualified, the argument it takes is a plain function int → ⟨l1⟩ intand has already resolved its own qualifiers. That is too eager for our purposes. For example, if
we apply foo (f1[⟨⟩]), under dictionary translation we would get foo ev1 (f1[⟨⟩] ev1). However, it
may well be that foo itself applies f1 under a new handler for the l1 effect and thus needs to pass
different evidence than ev1! Effectively, dictionary translation may partially apply functions with
their dictionaries which is not legal for handler evidence. The qualified type we really require for
foo uses higher-ranked qualifiers, something like Ev l1⇒ (Ev l1⇒ int → ⟨l1⟩ int) → ⟨l1⟩ int.
4.1 Evidence VectorsThe design we present here instead passes all evidence as a single evidence vector to each (effectful)
function: this keeps the runtime representations stable under type instantiation, and we can ensure
syntactically that functions are never partially applied to evidence.
Figure 6 defines our target language Fev as an explicitly typed calculus with evidence passing.
All applications are now of the form e1 w e2 where we always pass an evidence vector w with the
original argument e2. Therefore, all lambdas are of the form λϵ z : evv ϵ, x :σ . e and always take
an evidence vector z besides their regular parameter x. We also extend application forms in the
evaluation context to take evidence parameters. The double arrow notation is used do denote the
type of these “tupled” lambdas:
σ1⇒ ϵ σ2 � evv ϵ → σ1→ ϵ σ2
During evidence translation, every effect type ϵ on an arrow is translated to an explicit runtime
evidence vector of type evv ϵ , and we translate type annotations as:
⌈·⌉ : σ → σ⌈∀α .σ ⌉ = ∀α . ⌈σ ⌉ ⌈α⌉ = α⌈τ1→ ϵ τ2⌉ = ⌈τ1⌉ ⇒ ϵ ⌈τ2⌉ ⌈c τ1 . . . τn⌉= c ⌈τ1⌉ . . . ⌈τn⌉
Evidence vectors are essentially a map from effect labels to evidence. During evaluation we need to
be able to select evidence from an evidence vector, and to insert new evidence when a handler is
instantiated, and we define the following three operations:
⟨⟨ ⟩⟩ : evv ⟨⟩ (empty evidence vector)
_.l : ∀µ . evv ⟨l | µ⟩ → ev l (select evidence from a vector)
⟨⟨l : ev | w⟩⟩ : ∀µ . ev l→ evv µ → evv ⟨l | µ⟩ (evidence insertion)
14
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
Where we assume the following two laws that relate selection and insertion:
⟨⟨l : ev | w⟩⟩.l = ev⟨⟨l′ : ev | w⟩⟩.l= w.l iff l , l′
Later we want to be able to select evidence from a vector with a constant offset instead of searching
for the label, so we are going to keep them in a canonical form ordered by the effect types l, writtenas ⟨⟨l1 : ev1, . . ., ln : evn⟩⟩ with every li ⩽ li+1. We can now define ⟨⟨l : ev | w⟩⟩ as notation for a vector
where evidence ev was inserted in an ordered way, i.e.
⟨⟨l : _ | _⟩⟩ : ∀µ . ev l→ evv µ → evv ⟨l | µ⟩⟨⟨l : ev | ⟨⟨⟩⟩⟩⟩ = ⟨⟨l : ev⟩⟩⟨⟨l : ev | ⟨⟨l′ : ev ′, w⟩⟩⟩⟩= ⟨⟨l′ : ev ′, ⟨⟨l : ev | w⟩⟩⟩⟩ iff l > l′
⟨⟨l : ev | ⟨⟨l′ : ev ′, w⟩⟩⟩⟩= ⟨⟨l : ev, l′ : ev ′, w⟩⟩ iff l ⩽ l′
Note how the dynamic representation as vectors of labeled evidence nicely corresponds to the
static effect row-types, in particular with regard to duplicate labels, which correspond to nested
handlers at runtime. Here we see why we cannot swap the position of equal effect labels as we need
the evidence to correspond to their actual order in the evaluation context. Inserting all evidence in
a vector w1 into another vector w2 is defined inductively as:
⟨⟨⟨⟨⟩⟩ | w2⟩⟩ = w2
⟨⟨⟨⟨l : ev,w1⟩⟩ | w2⟩⟩= ⟨⟨l : ev | ⟨⟨w1 | w2⟩⟩⟩⟩
and evidence selection can be defined as:
_.l : ∀µ . evv ⟨l | µ⟩ → ev l⟨⟨l : ev, _⟩⟩.l = ev⟨⟨l′ : ev,w⟩⟩.l= w.l iff l , l′
⟨⟨ ⟩⟩.l = (cannot happen)
4.2 Evidence TranslationThe evidence translation is already defined in Figure 5, in the gray parts of the rules. The full rules
for expressions are of the form Γ;w ⊢ e : σ | ϵ ⇝ e′ where given a context Γ, the expression ehas type σ with effect ϵ . The rules take the current evidence vector w for the effect ϵ , of type evv ϵ ,and translate to an expression e′ of System Fev .
The translation in itself is straightforward where we only need to ensure extra evidence is passed
during applications and abstracted again on lambdas. The abs rule abstracts fully over all evidence
in a function as λϵ z : evv ϵ, x :σ1. e′, where the evidence vector is abstracted as z and passed to its
premise. Note that since we are translating, z is not part of Γ here (which scopes over Fϵ terms).
The type rules for Fev , discussed below, do track such variables in the context. The dual of this is
rule app which passes the effect evidence w as an extra argument to every application as e′1w e′
2.
To prove preservation and coherence of the translation, we also include a translation rule for
handle, even though we assume these are internal. Otherwise there are no surprises here and the
main difficulty lies in the operational rules, which we discuss in detail in Section 4.4.
To prove additional properties about the translated programs, we define a more restricted set of
typing rules directly over System Fev in Figure 9 of the form Γ;w ⊩ e : σ | ϵ (ignoring the grayparts), such that Γ ⊢ w : evv ϵ , and where the rules are a subset of the general typing rules for Fϵ .Using this, we prove that the translation is sound:
Theorem 4. (Evidence translation is Sound in Fev)If ∅; ⟨⟨⟩⟩ ⊢ e : σ | ⟨⟩ ⇝ e′ then ∅; ⟨⟨⟩⟩ ⊩ e′ : ⌈σ ⌉ | ⟨⟩.
15
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
4.3 CorrespondenceThe evidence translation maintains a strong correspondence between the effect types, the evidence
vectors, and the evaluation contexts. To make this precise, we define the (reverse) extraction of all
handlers in a context E as ⌈E⌉ where:
⌈F1 · handlem1h1 · . . . · Fn · handlemn hn · F⌉ = ⟨⟨ln : (mn, hn) | . . . | l1 : (m1, h1) | ⟨⟨⟩⟩⟩⟩
⌈F1 · handlem1h1 · . . . · Fn · handlemn hn · F⌉
l = ⟨ln, . . ., l1⟩⌈F1 · handlem1
h1 · . . . · Fn · handlemn hn · F⌉m= {mn, . . ., m1}
With this we can characterize the correspondence between the evaluation context and the evidence
used at perform:
Lemma 6. (Evidence corresponds to the evaluation context)If ∅;w ⊩ E[e] : σ | ϵ then for some σ1 we have ∅; ⟨⟨⌈E⌉ | w⟩⟩ ⊩ e : σ1 | ⟨⌈E⌉l | ϵ⟩,and ∅;w ⊩ E : σ1→ σ | ϵ .
Lemma 7. (Well typed operations are handled)If ∅; ⟨⟨⟩⟩ ⊩ E[perform op σ v] : σ | ⟨⟩ then E has the form E1 · handlewm h · E2 with op ̸∈ bop(E2)
and op→ f ∈ h.
These brings us to our main theorem which states that the evidence passed to an operation
corresponds exactly to the innermost handler for that operation in the dynamic evaluation context:
Theorem 5. (Evidence Correspondence)If∅; ⟨⟨⟩⟩ ⊩ E[perform op σ w v] : σ | ⟨⟩ then E has the form E1 · handlew
′
m h · E2 with op ̸∈ bop(E2),
op→ f ∈ h, and the evidence corresponds exactly to dynamic execution context such thatw.l = (m, h).
4.4 Operational Rules of System Fev
The operational rules for System Fev are defined in Figure 6. Since every application now always
takes an evidence vector argument w the new (app) and (handler) rules now only reduce when
both arguments are present (and the syntax does not allow for partial evidence applications).
The (handler) rule differs from System Fϵ in two significant ways. First, it saves the current
evidence in scope (passed as w) in the handle frame itself as handlewm. Secondly, the evidence vectorit passes on to its action is now extended with its own unique evidence, as ⟨⟨l : (m, h) | w⟩⟩.
In the (perform) rule, the operation clause (op→ f ) ∈ h is now translated itself, and we need to
pass evidence to f . Since it takes two arguments, the operation payload x and its resumption k,the application becomes (f [σ ] w x) w k. The evidence we pass to f is the evidence of the originalhandler context saved as handlew in the (handler) rule. In particular, we should not pass the evidencew ′ of the operation, as that is the evidence vector of the context in which the operation itself
evaluates (and an extension of w). In contrast, we evaluate each clause under their original context
and need the evidence vector corresponding to that. In fact, we can even ignore the evidence vector
w ′ completely for now as we only need to use it later for implementing optimizations.
4.5 Guarded Context Instantiation and Scoped ResumptionsThe definition of the resumption k in the (perform) rule differs quite a bit from the original definition
in System Fϵ (Figure 2), which was:
k = λϵx :σ2[α :=σ ]. handleϵ h · E · x
while the Fev definition now uses:
k = guardw (handlewm h · E) (σ2[α :=σ ])
16
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
where we use a the new Fev value term guardw E σ . Since k has a regular function type, it now
needs to take an extra evidence vector, and we may have expected a more straightforward extension
without needing a new guard rule, something like:
k = λϵ z : evv ϵ, x :σ2[α :=σ ]. handleϵ h · E · xbut then the question becomes what to do with that passed in evidence z? This is the point whereit becomes more clear that resumptions are special and not quite like a regular lambda since they
restore a captured context. In particular, the context E that is restored has already captured theevidence of the original context in which it was captured (as w), and thus may not match the evidenceof the context in which it is resumed (as z)!The new guarded application rule makes this explicit and only restores contexts that are resumed
under the exact same evidence, in other words, only scoped resumptions are allowed:
(guardw E σ ) w v −→ E[v]If the evidence does not match, the evaluation is stuck in Fev .
As an example of how this can happen, we return to our evil example in Section 2.2 which uses
non-scoped resumptions to change the meaning of op1. Since we are now in a typed setting, we
modify the example to return a data type of results to make everything well-typed:
data res = again : (() → ⟨one⟩ res) → res| done : int → res
Σ = { one : { op1
: () → int }, evil : { opevil : () → () } }
with the following helper definitions:
h1 = { op1→ λx k. k 1 } f (again k)= handler h2 (λ_. k ()); 0
h2 = { op1→ λx k. k 2 } f (done x) = x
hevil= { opevil → λx k. (again k) }
body = perform op1(); perform opevil (); perform op
1(); done 0
and where the main expression is evidence translated as:
f (handler h1 (λ_. handler hevil (λ_. body)))⇝ f ⟨⟨⟩⟩ (handler h1 ⟨⟨⟩⟩ (λz, _. handler hevil z(λz : evv ⟨one, evil⟩, _. perform op
1z (); perform opevil z (); perform op
1z (); done 0)))
Starting evaluation in the translated expression, we can now derive:
7−→∗ f ⟨⟨⟩⟩ · handle⟨⟨⟩⟩m1h1 · handle
w1
m2hevil · (□; perform op
1w2 (); done 0) · perform opevil w2 ()
with w1 = ⟨⟨one : (m1, h1)⟩⟩, w2 = ⟨⟨evil : (m2, hevil), one : (m1, h1)⟩⟩
7−→∗ f ⟨⟨⟩⟩ · handle⟨⟨⟩⟩m1h1 · (λz x z k. (again k)) w1 () w1 k
with k = guardw1 (handlew1
m2hevil · (□; perform op
1w2 (); done 0))
7−→∗ f ⟨⟨⟩⟩ · handle⟨⟨⟩⟩m1h1 · (again k)
7−→∗ f ⟨⟨⟩⟩ (again k)7−→ handler h2 ⟨⟨⟩⟩ (λz _. k z ())7−→∗ handle⟨⟨⟩⟩m3
h2 · k w3 () with w3 = ⟨⟨one : (m3, h2)⟩⟩
= handle⟨⟨⟩⟩m3h2 · guardw1 (handlew1
m2hevil ·□; perform op
1w2 (); done 0) w3 ()
At this point, the guard rule gets stuck as we have captured the context originally under evidence
w1, but we try to resume with evidence w3, and w1 = ⟨⟨one : (m1, h1)⟩⟩ , ⟨⟨one : (m3, h2)⟩⟩ = w3.
If we allow the guarded context instantiation anyways we get into trouble when we try to
perform op1again:
7−→ handle⟨⟨⟩⟩m3h2 · handle
w1
m2hevil · (() ; perform op
1w2 (); done 0)
7−→∗ handle⟨⟨⟩⟩m3h2 · handle
w1
m2hevil · (□; done 0) · perform op
1w2 ()
17
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
in that case the innermost handler for op1is now h2 while the evidence w2.l is (m1, h1) and it
no longer corresponds to the dynamic context! (and that would void our main correspondence
Theorem 5 and in turn invalidate optimizations based on this).
4.6 Uniqueness of HandlersIt turns out that to guarantee coherence of the translation to plain polymorphic lambda calculus,
as discussed in Section 5, we need to ensure that all m’s in an evaluation context are always
unique. This is a tricky property; for example, uniqueness of markers does not hold for arbitrary
Fev expressions: markers may be duplicated inside lambdas outside of the evaluation context, and
we can also construct an expression manually with duplicated markers, e.g. handlewm · handlewm · e.
However, we can prove that if we only consider initial Fev expressions without handlewm, or anyexpressions reduced from that during evaluation, then it is guaranteed that all m’s are always
unique in the evaluation context – even though the (handler) rule introduces handlewm during
evaluation, and the (app) rule may duplicate markers.
Definition 1. (Handle-safe expressions)A handle-safe Fev expression is a well-typed closed expression that either (1) contains no handlewmterm; or (2) is itself reduced from a handle-safe expression.
Theorem 6. (Uniqueness of handlers)For any handle-safe Fev expression e, if e = E1 · handle
w1
m1h · E2 · handle
w2
m2h · e0, then m1 , m2.
4.7 Preservation and CoherenceAs exemplified above, the guard rule is also essential to prove the preservation of evidence typings
under evaluation. In particular, we can show:
Theorem 7. (Preservation of evidence typing)If ∅; ⟨⟨⟩⟩ ⊩ e1 : σ | ⟨⟩ and e1 7−→ e2, then ∅; ⟨⟨⟩⟩ ⊩ e2 : σ | ⟨⟩.
e1 e2 e3
e′3
e′2
e′′3
e′1
e′′2
e′′′3
stuck
Fϵ Fϵ
�Fev
� �Fev Fev
Fig. 7. Coherence
Even more important though is to show that our translation
is coherent, that is, if we take an evaluation step in System
Fϵ , the evidence translated expression will take a similar
step such that the resulting expression is again a translation
of the reduced Fϵ expression:
Theorem 8. (Evidence translation is coherent)If ∅; ⟨⟨⟩⟩ ⊢ e1 : σ | ⟨⟩ ⇝ e′
1and e1 7−→ e2, and (due to
preservation) ∅; ⟨⟨⟩⟩ ⊢ e2 : σ | ⟨⟩ ⇝ e′2, then exists a e′′
2,
such that e′17−→ e′′
2and e′′
2� e′
2.
Interestingly, the theorem states that the translated e′2is
only coherent under an equivalence relation � relation
to the reduced expression e′2, as illustrate in Figure 7. The
reason that e′2and e′′
2are not directly equal is due to guard expressions only being generated by
reduction. In particular, if we have a Fϵ reduction of the form:
handleϵ h · E · perform op σ v −→ f σ v k with k = λϵx :σ ′. handleϵ h · E · xthen the translation takes the following Fev reduction:handlewm h · E′ · perform op ⌈σ ⌉ w ′ v ′ −→ f ′ ⌈σ ⌉ w v ′ w k′ with k′ = guardw (handlewm h′ · E′) σ ′
At this point the translation of f σ v k will be of the form f ′ ⌈σ ⌉ w ′ v ′ w ′ k′′ wherek′′ = λϵ z : evv ϵ, x . handleϵ h′ · E′′ · x
18
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
Expressions e ::= v | e e | e[σ ]Values v ::= x | λx :σ . e | Λαk . v
(app) (λϵx :σ . e) v −→ e[x:=v](tapp) (Λαk . v) [σ ] −→ v[α :=σ ]
Context F ::= □ | F e | v F | F [σ ]E ::= F
x : σ ∈ Γ
Γ ⊢F xσ : σ[fvar]
Γ ⊢F v : σ
Γ ⊢F Λαk . v : ∀αk . σ[ftabs]
Γ, x :σ1 ⊢F e : σ2
Γ ⊢F λx :σ1. e : σ1→ σ2
[fabs]
Γ ⊢F e1 : σ1→ σ Γ ⊢ e2 : σ
Γ ⊢F e1 e2 : σ[fapp]
Γ ⊢F e : ∀αk . σ1 ⊢wf σ : k
Γ ⊢F e[σ ] : σ1[α :=σ ][ftapp]
Fig. 8. System Fv : explicitly typed (higher kinded) polymorphic lambda calculus with strict evalua-
tion. Types as in Figure 3 with no effects on the arrows.
i.e. the resumption k is translated as a regular lambda now and not as guard! Also, since E is
translated now under a lambda, the resulting E′′ differs in all evidence terms w in E′ which will be
z instead.However, we know that if the resumption k′ is ever applied, the argument is either exactly w,
in which case E′′[z:=w] = E′, or not equal to w in which case the evidence translated program
gets stuck. This is captured by � relation which is the smallest transitive and reflexive congruence
among well-typed Fev expressions, up to renaming of unique markers, satisfying the eq-guard rule,
which captures the notion of guarded context instantiation.
e[z:=w] � E[x]
λϵ z, x :σ . e � guardw E σ[eq-guard]
Now, is this definition of equivalence strong enough? Yes, because we can show that if two translated
expressions are equivalent, then they stay equivalent under reduction (or get stuck):
Lemma 8. (Operational semantics preserves equivalence, or gets stuck)If e1 � e2, and e1 −→ e′
1, then either e2 is stuck, or we have e′2 such that e2 −→ e′
2and e′
1� e′
2.
This establishes the full coherence of our evidence translation: if a translated expression reduces
under Fev without getting stuck, the final value is equivalent to the value reduced under System Fϵ .Moreover, the only way an evidence translated expression can get stuck is if it uses non-scoped
resumptions.
Note that the evidence translation never produces guard terms, so the translated expression can
always take an evaluation step; however, subsequent evaluation steps may lead to guard terms, so
after the first step, it may get stuck if a resumption is applied under a different handler context
than where it was captured.
5 TRANSLATION TO CALL-BY-VALUE POLYMORPHIC LAMBDA CALCULUSNow that we have a strong correspondence between evidence and the dynamic handler context, we
can translate System Fev expressions all the way to the call-by-value polymorphic lambda calculus,
System Fv . This is important in practice as it removes all the special evaluation and type rules
of algebraic effect handlers; this in turn means we can apply all the optimizations that regular
compilers perform, like inlining, known case expansion, common sub-expression elimination etc.
as usual with needing to keep track of effects. Moreover, it means we can compile directly to most
19
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
Γ↑; w↑Fev
;w ′↑Fv
⊩ e↑Fev
: σ↓| ϵ↑⇝ e′↓Fv
Γ↑⊩val v
↑Fev
: σ↓⇝ v ′
↓Fv
Γ↑⊩ops h
↑Fev
: σ↓| l↓| ϵ↑⇝ h′
↓Fv
x :σ ∈ Γ
Γ ⊩val x : σ ⇝ x[mvar]
Γ ⊩val v : σ ⇝ v ′
Γ ⊩val Λα . v : ∀α . σ ⇝ Λα . v ′[mtabs]
(Γ, z : evv ϵ, x :σ1); z ; z ⊩ e : σ2 | ϵ ⇝ e′
Γ ⊩val λϵ z : evv ϵ, x :σ1. e : σ1⇒ ϵ σ2 ⇝ λz x . e′[mabs]
Γ ⊩val v : σ ⇝ v ′
Γ;w ;w ′ ⊩ v : σ | ϵ ⇝ pure[⌊σ ⌋] v ′[mval]
Γ;w ;w ′ ⊩ e : ∀α . σ1 | ϵ ⇝ e′
Γ;w ;w ′ ⊩ e[σ ] : σ1[α :=σ ] | ϵ ⇝ e′ ▷ (λx . pure (x[⌊σ ⌋]))[mtapp]
Γ;w ;w ′ ⊩ e1 : σ2⇒ ϵ σ | ϵ ⇝ e′1
Γ;w ;w ′ ⊩ e2 : σ2 | ϵ ⇝ e′2
Γ;w ;w ′ ⊩ e1 w e2 : σ | ϵ ⇝ e′1▷ (λf . (e′
2▷ f w ′))
[mapp]
Γ;w ;w ′ ⊩ec E : σ1→ σ2 | ϵ ⇝ e′ Γ ⊩val w : evv ϵ ⇝ w ′
Γ ⊩val guardw E σ1 : σ1⇒ ϵ σ2 ⇝ guard w′ e′[mguard]
op : ∀α . σ1→ σ2 ∈ Σ(l)
Γ ⊩val performϵ op σ : σ1[α :=σ ]⇒ ⟨l | ϵ⟩ σ2[α :=σ ] ⇝ performop[⟨l | ϵ⟩, ⌊σ ⌋][mperform]
opi : ∀α . σ1→ σ2 ∈ Σ(l) α ̸∩ ftv(ϵ σ )Γ ⊩val fi : ∀α . σ1⇒ ϵ (σ2⇒ ϵ σ )⇒ ϵ σ ⇝ f ′i
Γ ⊩ops { op1→ f1, . . ., opn→ fn } : σ | l | ϵ ⇝ { op
1→ f ′
1, . . ., opn→ f ′n }
[mops]
Γ ⊩ops h : σ | l | ϵ ⇝ h′
Γ ⊩val handlerϵ h : (()⇒ ⟨l | ϵ⟩ σ )⇒ ϵ σ ⇝ handler l[ϵ, ⌊σ ⌋] h′[mhandler]
Γ ⊩ops h : σ | l | ϵ ⇝ h′ Γ; ⟨⟨l : (m, h) | w⟩⟩; ⟨⟨l : (m, h′) | w ′⟩⟩ ⊩ e : σ | ⟨l | ϵ⟩ ⇝ e′
Γ;w ;w ′ ⊩ handlewm h e : σ | ϵ ⇝ prompt[ϵ, ⌊σ ⌋] m w ′ e′[mhandle]
Fig. 9. Monadic translation to System-Fv . ((▷) is monadic bind).
common host platforms, like C or WebAssembly without needing a special runtime system to
support capturing the evaluation context.
There has been previous work that performs such translation [Forster et al. 2019; Hillerström et
al. 2017; Leijen 2017c], as well as various libraries that embed effect handlers as monads [Kammar
et al. 2013; Wu et al. 2014] but without evidence translation such embeddings require either a
sophisticated runtime system [Dolan et al. 2017 2015; Leijen 2017a], or are not quite as efficient
as one might hope. The translation presented here allows for better optimization as it maintains
evidence and has no special runtime requirements (it is just F!).
20
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
5.1 Translating to Multi-Prompt Delimited ContinuationsAs a first step, we show that we do not need explicit handle frames anymore that carry around the
handler operations h, but can translate to multi-prompt delimited continuations [Brachthäuser and
Schuster 2017]. Gunter, Rémy, and Riecke [1995] present the set and cupto operators for named
prompts m with the following “control-upto” rule:
set m in · E · cupto m as x in e −→ (λk. e) (λx . E · x) m ̸∈ ⌈E⌉m
This effectively exposes “shallow” multi-prompts: for our purposes, we always need “deep” handling
where the resumption evaluates under the same prompt again and we define:
promptm e � set m in eyieldm f � cupto m as k in (f (λx . set m in (k x)))
which gives us the following derived evaluation rule:
promptm · E · yieldm f −→ f (λx . promptm · E · x) m ̸∈ ⌈E⌉m
This is almost what we need, except that we need a multi-prompt that also takes evidence w into
account and uses guard instead of a plain lambda to apply the resumption, i.e.:
promptwm · E · yieldm f −→ f w (guardw (promptwm · E)) m ̸∈ ⌈E⌉m
Using the correspondence property (Theorem 5), we can use the evidence to inspect the handler
locally at the perform and no longer need to keep it in the handle frame. We can now translate
both perform op v w and handlewm h in terms of the simpler yieldm and promptwm, as:
⌈handlewm h⌉ = promptwm⌈perform op w′ v⌉= yieldm (λw k. f w v w k) with (m, h) = w ′.l and (op→ f ) ∈ h
We prove that this is a sound interpretation of effect handling:
Theorem 9. (Evidence Translation to Multi-Prompt Delimited Continuations is Sound)For any evaluation step e1 7−→ e2 we also have ⌈e1⌉ 7−→
∗ ⌈e2⌉.
Dolan et al. [2015] describe the multi-core OCaml runtime system with split stacks; in such setting
we could use the pointers to a split point as markers m, and directly yield to the correct handler
with constant time capture of the context. Even with such runtime, it may still be beneficial to do a
monadic translation as well in order to be able to use standard compiler optimizations.
5.2 Monadic Multi-Prompt Translation to System Fv
With the relation to multi-prompt delimited control established, we can now translate Fev to Fv ina monadic style, where we use standard techniques [Dyvbig et al. 2007] to implement the delimited
control as a monad. Assuming notation for data types and matching, we can define a multi-prompt
monad mon as follows:
data mon µ α =| pure : α → mon µ α| yield : ∀β r µ ′. marker µ ′ r → ((β → mon µ ′ r) → mon µ ′ r) → (mon µ β → mon µ α) → mon µ α
pure x = pure xyield m clause= yield m clause id
The pure case is used for value results, while the yield implements yielding to a prompt. A
yield m f cont has three arguments, (1) the marker m : marker µ ′ r bound to a prompt in some
context with effect µ ′ and answer type r ; (2) the operation clause which receives the resumption
(of type β → mon µ ′ r) where β is the type of the operation result; and finally (3) the current
21
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
continuation cont which is the runtime representation of the context. When binding a yield, thecontinuation keeps being extended until the full context is captured:
(f ◦ g) x = f (g x) (function composition)
(f • g) x = g x ▷ f (Kleisli composition)
(pure x) ▷ g = g x (monadic bind)
(yield m f cont) ▷ g= yield m f (g • cont)
The hoisting of yields corresponds closely to operation hoisting as described by Bauer and Pret-
nar [2015]. The prompt operation has three cases to consider:
prompt : ∀µ α . marker µ α → evv µ → mon ⟨l | µ⟩ α → mon µ αprompt m w (pure x) = pure xprompt m w (yield m′ f cont)= yield m′ f (prompt m w ◦ cont) if m , m′
prompt m w (yield m f cont) = f w (guard w (prompt m w ◦ cont))
In the pure case, we are at the (value) rule and return the result as is. If we find a yield that yields
to another prompt we also keep yielding but remember to restore our prompt when resuming in its
current continuation, as (prompt m w ◦ cont). The final case is when we yield to the prompt itself,
in that case we are in the (yield) transition and continue with f passing the context evidence wand a guarded resumption
3.
The guard operation simply checks if the evidence matches and either continues or gets stuck:
guard w1 cont w2 x= if (w1 == w2) then cont (pure x) else stuck
Note that due to the uniqueness property (Theorem 6)we can check the equalityw1 == w2 efficiently
by only comparing the markers m (and ignoring the handlers). The handle and perform can be
translated directly into prompt and yield as shown in the previous section, where we generate a
handler l definition per effect l, and a performopfor every operation:
handler l : ∀µ α . hndl µ α → evv µ → (evv ⟨l | µ⟩ → () → mon ⟨l | µ⟩ α) → mon µ αperformop
: ∀µ α . evv ⟨l | µ⟩ → σ1→ mon ⟨l | µ⟩ σ2 with op :∀α . σ1→ σ2 ∈ Σ(l)handler l h w f = freshm (λm→ prompt m w (f ⟨⟨l : (m, h) | w⟩⟩ ()))performop w x = let (m, h) = w.l in yield m (λw k. ((h.op) w x ▷ (λf . f w k)))
The handler creates a fresh marker and passes on new evidence under a new prompt. The performcan now directly select the evidence (m, h) from the passed evidence vector and yield to m directly.
The function passed to yield is a bit complex since each operation clause is translated normally and
has a nested monadic type, i.e. evv ϵ → mon ϵ ((β → mon ϵ r) → mon ϵ r), so we need to bind thefirst partial application to x before passing the continuation k.
Finally, for every effect signature l : sig ∈ Σ we declare a corresponding data type hndl ϵ r thatis a record of operation clauses:
l : { op1
: ∀α1. σ1→ σ ′1, . . ., opn : ∀αn. σn→ σ ′n }
⇝ data hndl µ r = hndl { op1
: ∀α1. op σ1 σ′1µ r, . . ., opn : ∀αn. op σn σ ′n µ r }
where operations op are a type alias defined as:
alias op α β µ r � evv µ → α → mon (evv µ → (evv µ → β → mon µ r) → mon µ r)
3Typing the third case needs a dependent match on the markers m′ : marker µ′ r and m = marker µ α where their
equality implies µ = µ′ and r = α . This can be done in Haskell with the Equal GADT, or encoded in Fv using explicitequality witnesses [Baars and Swierstra 2002].
22
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
λϵ
Fϵ
Fev
Fv
e∗1
e∗2
Γ;w ⊢ e1 :σ | ϵ(Fig. ??)
Γ;w ⊢ e2 :σ | ϵPreservation (Thm. 3.5)
Γ;w ⊩ e′1
: ⌈σ ⌉ | ϵ(Fig. ??)
Γ;w ⊩ e′′′2
: ⌈σ ⌉ | ϵPreservation (Thm. 4.7)
Γ;w ⊩ e′2
: ⌈σ ⌉ | ϵ�(Fig. ??)
Coherence (Thm. 4.7)
Γ ⊢F e′′1
:mon ϵ ⌊σ ⌋(Fig. ??)
Γ ⊢F e′′2
:mon ϵ ⌊σ ⌋
σ
w
▷
steps to (Fig. ??)
Progress (Thm. 3.5)
steps to (Fig. ??)
Soundness (Thm. 4.2) Soundness (Thm. 4.2)
erase∗
erase∗
steps to (Fig. ??)
=
Correspondence (Thm. 3.3)
Soundness (Thm. 5.2) Soundness (Thm. 5.2)
steps to (Fig. ??)
Coherence (Thm. 5.2)
*
Fig. 10. An overview how the various theorems establish the relations between the different calculi
With these definitions in place, we can do a straightforward type directed translation from Fev toFv by just lifting all operations into the prompt monad, as shown in Figure 9. Types are translated
by making all effectful functions monadic:
⌊∀α . σ ⌋ = ∀α . ⌊σ ⌋ ⌊σ1⇒ ϵ σ2⌋ = evv ϵ → ⌊σ1⌋ → mon ϵ ⌊σ2⌋
⌊α⌋ = α ⌊c σ1 . . . σn⌋ = c ⌊σ1⌋ . . . ⌊σn⌋
We prove that these definitions are correct, and that the resulting translation is fully coherent,
where a monadic program evaluates to the same result as a direct evaluation in Fev .
Theorem 10. (Monadic Translation is Sound)If ∅; ⟨⟨⟩⟩; ⟨⟨⟩⟩ ⊩ e : σ | ⟨⟩ ⇝ e′, then ∅ ⊢F e′ : mon ⟨⟩ ⌊σ ⌋.
Theorem 11. (Coherence of the Monadic Translation)If∅; ⟨⟨⟩⟩; ⟨⟨⟩⟩ ⊩ e1 : σ | ⟨⟩ ⇝ e′
1and e1 −→ e2, then also∅; ⟨⟨⟩⟩; ⟨⟨⟩⟩ ⊩ e2 : σ | ⟨⟩ ⇝ e′
2where e′
1−→∗ e′
2.
Together with earlier results we establish full soundness and coherence from the original typed effect
handler calculus Fϵ to the evidence based monadic translation into plain call-by-value polymorphic
lambda calculus Fv . See Figure 10 for how our theorems relate these systems to each other.
6 OPTIMIZATIONSWith a fully coherent evidence translation to plain polymorphic lambda calculus in hand, we can
now apply various transformations in that setting to optimize the resulting programs.
6.1 Partially Applied HandlersIn the current performop
implementation, we yield with a function that takes evidence w to pass on
to the operation clause f , as:
λw k. ((h.op) w x ▷ (λf . f w k))
23
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
However, the w that is going to be passed in is always that of the handlew frame. When we
instantiate the handlew we can in principle map the w in advance over all operation clause so these
can be partially evaluated over the evidence vector:
handler l h w f = freshm (λm→ prompt m w (f ⟨⟨l : (m, pmapl h w | w⟩⟩ ()))
pmapl (hndl f1 . . . fn) w= phndl (partial w f1) . . . (partial w fn)partial w f = λx k. (f w x ▷ (λf ′. f ′ w k))
The pmapl function creates a new handler data structure phndl where every operation is now
partially applied to the evidence which results in simplified type for each operation (as expressed
by the pop type alias):
alias pop α β µ r � α → (β → mon µ r) → mon µ r
The perform is now simplified as well as it no longer needs to bind the intermediate application:
performop w x= let (m, h) = w.l in yield m (λk. (h.op) x k)
Finally, the prompt case where the marker matches no longer needs to pass evidence as well:
. . .prompt m w (yield m f cont) = f (guard w (prompt m w ◦ cont))
By itself, the impact of this optimization will be modest, just allowing inlining of evidence in fclauses, and inlining the monadic bind over the partial application, but it opens up the way to do
tail resumptive operations in-place.
6.2 Evaluating Tail Resumptive Operations In PlaceIn practice, almost all important effects are tail-resumptive. The main exceptions we know of are
asynchronous I/O (but that is dominated by I/O anyways) and the ambiguity effect for resuming
multiple times. As such, we expect the vast majority of operations to be tail-resumptive, and being
able to optimize them well is extremely important. We can extend the partially evaluated handler
approach to optimize tail resumptions as well. First we extend the pop type to be a data type that
signifies if an operation clause is tail resumptive or not:
data pop α β µ r = tail : (α → mon µ β) → pop α β µ r| normal : (α → (β → mon µ r) → mon µ r) → pop α β µ r
The partial function now creates tail terms for any clause f that the compiler determined to be tail
resumptive (i.e. of the form λx k. k e) with k ̸∈ fv(e):
partial w f = tail (λx . (f w x ▷ (λf ′. f ′ w pure)) if f is tail resumptive
partial w f = normal (λx k. (f w x ▷ (λf ′. f ′ w k)) otherwise
Instead of passing in an “real” resumption function k, we just pass pure directly, leading to
λx . (e ▷ pure) – and such clause we can now evaluate in-place without needing to yield and capture
our resumption context explicitly. The performopcan directly inspect the form of the operation
clause from its evidence, and evaluate in place when possible:
performop w x = let (m, h) = w.l in case h.op of | tail f → f x| normal f → yield m (f x)
Ah, beautiful! Moreover, if a known handler is applied over some expression, regular optimizations
like inlining and known-case evaluation, can often inline the operations fully. As everything has
been translated to regular functions and regular data types without any special evaluation rules,
there is no need for special optimization rules for handlers either.
24
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
6.3 Using Constant Offsets in Evidence VectorsThe performop
operation is now almost as efficient as a virtual method call for tail resumptive
operations (just check if it is tail and do in indirect call), except that it still needs to do a dynamic
lookup for the evidence as w.l.The trick here is to take advantage of the canonical order of the evidence in a vector, where the
location of the evidence in a vector of a closed effect type is fully determined. In particular, for any
evidence vector w of type evv ⟨l | ϵ⟩ where ϵ is closed, we can replace w.l by a direct index w[ofs]where (l in ϵ) = ofs, defined as:
l in ⟨⟩ = 0
l in ⟨l′ | ϵ⟩= l in ϵ iff l ⩽ l′
l in ⟨l′ | ϵ⟩= 1 + (l in ϵ) iff l > l′
This means for any functions with a closed effect, the offset of all evidence is constant. Only
functions that are polymorphic in the effect tail need to index dynamically. It is beyond the scope
of this paper to discuss this in detail but we believe that even in those cases we can index by a
direct offset: following the same approach as TREX [Gaster and Jones 1996], we can use qualified
types internally to propagate (l in µ) constraints where the “dictionary” is simply the offset in the
evidence vector (and these constraints can be hidden from the user as we can always solve them).
6.4 Reducing Continuation AllocationThe monadic translation still produces inefficiencies as it captures the continuation at every
point where an operation may yield. For example, when calling an effectful function foo, as inx ← foo (); e, the monadic translation produces a bind which takes an allocated lambda as a second
argument to represent the continuation e explicitly, as foo () ▷ (λx . e).First of all, we can do a selective monadic translation [Leijen 2017c] where we leave out the
binds if the effect of a function can be guaranteed to never produce a yield, e.g. total functions (likearithmetic), all effects provided by the host platform (like I/O), and all effects that are statically
guaranteed to be tail resumptive (called linear effects). It turns out that many (leaf) functions satisfy
this property so this removes the vast majority of binding.
Secondly, since we expect the vast majority of operations to be tail resumptive, almost always
the effectful functions will not yield at all. It therefore pays off to always inline the bind operation
and perform a direct match on the result and inline the continuation directly, e.g. expand to:
case foo () of | yield m f cont → yield m f ((λx . e) • cont)| pure x → e
This can be done very efficiently, and is close to what a C or Go programmer would write: returning
a (yielding) flag from every function and checking the flag before continuing. Of course, this is also
a dangerous optimization as it duplicates the expression e, and more research is needed to evaluate
the impact of code duplication and finding a good inlining heuristic.
As a closing remark, the above optimization is why we prefer the monadic approach over
continuation passing style (CPS). With CPS, our example would pass the continuation directly
as foo () (λx . e). This style may be more efficient if one often yields (as the continuation is more
efficiently composed versus bubbling up through the binds [Ploeg and Kiselyov 2014]) but it prohibits
our optimization where we can inspect the result of foo (without knowing its implementation) and
to only allocate a continuation if it is really needed.
7 RELATEDWORKIn the paper, we compare to related work mostly inline when we discuss various aspects. In what
follows, we briefly discuss more related work.
25
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
The work by Forster et al. [2019] is close to our work as it shows how delimited control, monads,
and effect handlers can express each other. They show in particular a monadic semantics for effect
handlers, but also prove that there does not exist a typed translation in their monomorphic setting.
They conjecture a polymorphic translation may exist, and this paper proves that such translation is
indeed possible.
Recent work by Biernacki et al. [2019] introduces labeled effect handlers where a handler can be
referred to by name; the generative semantics with global labels is similar to our runtime markers
m, but these labels are not guaranteed to be unique in the evaluation context (and they use the
innermost handler in such case). Similar to this work they also distinguish between the generative
handler (as handlea), and the expression form handlem (as handlel).Brachthäuser et al. [2020] use capability passing to perform operations directly on a specific
handler [Brachthäuser and Schuster 2017; Brachthäuser et al. 2018]. This is also similar to the work
of Zhang and Myers [2019] where handlers are passed by name as well. Both of these approaches
can be viewed as programming with explicit evidence (capabilities) and we can imagine extending
our calculus to allow a programmer to refer explicitly to the evidence (name) of a handler.
8 CONCLUSIONWe have shown a full formal and coherent translation from a polymorphic core calculus for effect
handlers (Fϵ ) to a polymorphic lambda calculus (Fv) based on evidence translation (through Fev),and we have characterized the relation to multi-prompt delimited continuations precisely. Besides
giving a new framework to reason about semantics of effect handlers, we are also hopeful that these
techniques will be used to create efficient implementations of effect handlers in practice. Moreover,
from a language design perspective, we expect that the restriction to scoped resumptions will be
more widely adopted. As future work, we would like to implement these techniques and integrate
them into real world languages.
REFERENCESArthur I. Baars, and S. Doaitse Swierstra. 2002. Typing Dynamic Typing. In Proceedings of the Seventh ACM SIGPLAN
International Conference on Functional Programming, 157–166. ICFP’02. Pittsburgh, PA, USA. doi:10.1145/581478.581494.Andrej Bauer, and Matija Pretnar. 2014. An Effect System for Algebraic Effects and Handlers. Logical Methods in Computer
Science 10 (4).Andrej Bauer, and Matija Pretnar. 2015. Programming with Algebraic Effects and Handlers. J. Log. Algebr. Meth. Program. 84
(1): 108–123. doi:10.1016/j.jlamp.2014.02.001.
Dariusz Biernacki, Maciej Piróg, Piotr Polesiuk, and Filip Sieczkowski. Dec. 2017. Handle with Care: Relational Interpretation
of Algebraic Effects and Handlers. Proc. ACM Program. Lang. 2 (POPL’17 issue): 8:1–8:30. doi:10.1145/3158096.Dariusz Biernacki, Maciej Piróg, Piotr Polesiuk, and Filip Sieczkowski. Dec. 2019. Binders by Day, Labels by Night: Effect
Instances via Lexically Scoped Handlers. Proc. ACM Program. Lang. 4 (POPL). Association for Computing Machinery,
New York, NY, USA. doi:10.1145/3371116.
Jonathan Immanuel Brachthäuser, and Philipp Schuster. Oct. 2017. Effekt: Extensible Algebraic Effects in Scala. In Scala’17.Vancouver, CA.
Jonathan Immanuel Brachthäuser, Philipp Schuster, and Klaus Ostermann. Oct. 2018. Effect Handlers for the Masses. Proc.ACM Program. Lang. 2 (OOPSLA). Association for Computing Machinery, New York, NY, USA. doi:10.1145/3276481.
Jonathan Immanuel Brachthäuser, Philipp Schuster, and Klaus Ostermann. 2020. Effekt: Capability-Passing Style for Type-
and Effect-Safe, Extensible Effect Handlers in Scala. Journal of Functional Programming. Cambridge University Press.
Lukas Convent, Sam Lindley, Conor McBride, and Craig McLaughlin. Jan. 2020. Doo Bee Doo Bee Doo. In the Journal ofFunctional Programming, January. To appear in the special issue on algebraic effects and handlers.
Stephen Dolan, Spiros Eliopoulos, Daniel Hillerström, Anil Madhavapeddy, KC Sivaramakrishnan, and Leo White. May
2017. Concurrent System Programming with Effect Handlers. In Proceedings of the Symposium on Trends in FunctionalProgramming. TFP’17.
Stephen Dolan, Leo White, KC Sivaramakrishnan, Jeremy Yallop, and Anil Madhavapeddy. Sep. 2015. Effective Concurrency
through Algebraic Effects. In OCaml Workshop.
26
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
R Kent Dyvbig, Simon Peyton Jones, and Amr Sabry. 2007. A Monadic Framework for Delimited Continuations. Journal ofFunctional Programming 17 (6). Cambridge University Press: 687–730. doi:10.1017/S0956796807006259.
Yannick Forster, Ohad Kammar, Sam Lindley, and Matija Pretnar. 2019. On the Expressive Power of User-Defined Effects:
Effect Handlers, Monadic Reflection, Delimited Control. Journal of Functional Programming 29. Cambridge University
Press: 15. doi:10.1017/S0956796819000121.
Ben R. Gaster, and Mark P. Jones. 1996. A Polymorphic Type System for Extensible Records and Variants. NOTTCS-TR-96-3.University of Nottingham.
Jean-Yves Girard. 1986. The System F of Variable Types, Fifteen Years Later. TCS.Jean-Yves Girard, Paul Taylor, and Yves Lafont. 1989. Proofs and Types. Cambridge University Press.
Carl A. Gunter, Didier Rémy, and Jon G. Riecke. 1995. A Generalization of Exceptions and Control in ML-like Languages. In
Proceedings of the Seventh International Conference on Functional Programming Languages and Computer Architecture,12–23. FPCA ’95. ACM, La Jolla, California, USA. doi:10.1145/224164.224173.
Daniel Hillerström, and Sam Lindley. 2016. Liberating Effects with Rows and Handlers. In Proceedings of the 1st InternationalWorkshop on Type-Driven Development, 15–27. TyDe 2016. Nara, Japan. doi:10.1145/2976022.2976033.
Daniel Hillerström, and Sam Lindley. 2018. Shallow Effect Handlers. In APLAS’18.Daniel Hillerström, Sam Lindley, Bob Atkey, and KC Sivaramakrishnan. Sep. 2017. Continuation Passing Style for Effect
Handlers. In Proceedings of the Second International Conference on Formal Structures for Computation and Deduction.FSCD’17.
Mark P. Jones. Feb. 1992. A Theory of Qualified Types. In 4th. European Symposium on Programming (ESOP’92), 582:287–306.Lecture Notes in Computer Science. Springer-Verlag, Rennes, France. doi:10.1007/3-540-55253-7_17.
Ohad Kammar, Sam Lindley, andNicolas Oury. 2013. Handlers in Action. In Proceedings of the 18th ACM SIGPLAN InternationalConference on Functional Programming, 145–158. ICFP ’13. ACM, New York, NY, USA. doi:10.1145/2500365.2500590.
Ohad Kammar, and Matija Pretnar. Jan. 2017. No Value Restriction Is Needed for Algebraic Effects and Handlers. Journal ofFunctional Programming 27 (1). Cambridge University Press. doi:10.1017/S0956796816000320.
Oleg Kiselyov, and Chung-chieh Shan. 2009. Embedded Probabilistic Programming. In Domain-Specific Languages.doi:10.1007/978-3-642-03034-5_17.
Daan Leijen. 2005. Extensible Records with Scoped Labels. In Proceedings of the 2005 Symposium on Trends in FunctionalProgramming, 297–312.
Daan Leijen. 2014. Koka: Programming with Row Polymorphic Effect Types. In MSFP’14, 5th Workshop on MathematicallyStructured Functional Programming. doi:10.4204/EPTCS.153.8.
Daan Leijen. Aug. 2016. Algebraic Effects for Functional Programming. MSR-TR-2016-29. Microsoft Research technical report.
Extended version of [Leijen 2017c].
Daan Leijen. 2017a. Implementing Algebraic Effects in C: Or Monads for Free in C. Edited by Bor-Yuh Evan Chang.
Programming Languages and Systems, LNCS, 10695 (1). Springer International Publishing, Suzhou, China: 339–363.
APLAS’17, Suzhou, China.
Daan Leijen. 2017b. Structured Asynchrony with Algebraic Effects. In Proceedings of the 2nd ACM SIGPLAN InternationalWorkshop on Type-Driven Development, 16–29. TyDe 2017. Oxford, UK. doi:10.1145/3122975.3122977.
Daan Leijen. Jan. 2017. Type Directed Compilation of Row-Typed Algebraic Effects. In Proceedings of the 44th ACM SIGPLANSymposium on Principles of Programming Languages (POPL’17), 486–499. Paris, France. doi:10.1145/3009837.3009872.
Sam Lindley, and James Cheney. 2012. Row-Based Effect Types for Database Integration. In Proceedings of the 8th ACMSIGPLAN Workshop on Types in Language Design and Implementation, 91–102. TLDI’12. doi:10.1145/2103786.2103798.
Sam Lindley, Connor McBride, and Craig McLaughlin. Jan. 2017. Do Be Do Be Do. In Proceedings of the 44th ACM SIGPLANSymposium on Principles of Programming Languages (POPL’17), 500–514. Paris, France. doi:10.1145/3009837.3009897.
Simon L Peyton Jones, and John Launchbury. 1995. State in Haskell. Lisp and Symbolic Comp. 8 (4): 293–341.
doi:10.1007/BF01018827.
Andrew M. Pitts. 1998. Existential Types: Logical Relations and Operational Equivalence. In In Proceedings of the 25thInternational Colloquium on Automata, Languages and Programming, 309–326. Springer-Verlag.
Atze van der Ploeg, and Oleg Kiselyov. 2014. Reflection without Remorse: Revealing a Hidden Sequence to Speed up Monadic
Reflection. In Proceedings of the 2014 ACM SIGPLAN Symposium on Haskell, 133–144. Haskell’14. Göthenburg, Sweden.doi:10.1145/2633357.2633360.
Gordon D. Plotkin, and John Power. 2003. Algebraic Operations and Generic Effects. Applied Categorical Structures 11 (1):69–94. doi:10.1023/A:1023064908962.
Gordon D. Plotkin, and Matija Pretnar. 2013. Handling Algebraic Effects. In Logical Methods in Computer Science, volume 9.
4. doi:10.2168/LMCS-9(4:23)2013.
Matija Pretnar. Dec. 2015. An Introduction to Algebraic Effects and Handlers. Invited Tutorial Paper. Electron. Notes Theor.Comput. Sci. 319 (C). Elsevier Science Publishers: 19–35. doi:10.1016/j.entcs.2015.12.003.
27
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
Matija Pretnar, Amr Hany Shehata Saleh, Axel Faes, and Tom Schrijvers. 2017. Efficient Compilation of Algebraic Effects andHandlers. CW Reports. Department of Computer Science, KU Leuven; Leuven, Belgium. https://lirias.kuleuven.be/retrieve/472230.
Didier Rémy. 1994. Type Inference for Records in Natural Extension of ML. In Theoretical Aspects of Object-OrientedProgramming, 67–95. doi:10.1.1.48.5873.
Philipp Schuster, Jonathan Immanuel Brachthäuser, and Klaus Ostermann. 2019. Staging Effects and Handlers – A Shift toZero-Cost Effect Handlers. Technical Report. University of Tübingen, Germany. http://ps.informatik.uni-tuebingen.de/publications/schuster19zero.
Sebastian Ullrich, and Leonardo de Moura. Sep. 2019. Counting Immutable Beans – Reference Counting Optimized for
Purely Functional Programming. In Proceedings of the 31st Symposium on Implementation and Application of FunctionalLanguages (IFL’19). Singapore.
Philip Wadler. Jul. 1990. Recursive Types for Free! University of Glasgow. http://homepages.inf.ed.ac.uk/wadler/papers/free-rectypes/free-rectypes.txt.
Andrew Wright. 1995. Simple Imperative Polymorphism. In LISP and Symbolic Computation, 343–356.Nicolas Wu, Tom Schrijvers, and Ralf Hinze. 2014. Effect Handlers in Scope. In Proceedings of the 2014 ACM SIGPLAN
Symposium on Haskell, 1–12. Haskell ’14. Göthenburg, Sweden. doi:10.1145/2633357.2633358.Yizhou Zhang, and Andrew C. Myers. Jan. 2019. Abstraction-Safe Effect Handlers via Tunneling. Proc. ACM Program. Lang.
3 (POPL). ACM. doi:10.1145/3290318.
28
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
⊢wf αk: k
[kind-var]
⊢wf ck : k[kind-con]
⊢wf ⟨⟩ : eff[kind-total]
⊢wf σ : ∗ k , lab
⊢wf ∀αk . σ : ∗[kind-qant]
⊢wf σ1 : k2→ k ⊢wf σ2 : k2
⊢wf σ1 σ2 : k[kind-app]
⊢wf ϵ : eff ⊢wf l : lab
⊢wf ⟨l | ϵ⟩ : eff[kind-row]
⊢wf σ1 : ∗ ⊢wf σ2 : ∗ ⊢wf ϵ : eff
⊢wf σ1→ ϵ σ2
[kind-arrow]
Fig. 11. Well-formedness of types.
APPENDICESA FULL RULESThis section contains the rules for well-formed types, and for typing and translating the evaluation
contexts.
A.1 Well Formed TypesThe kinding rules for types are shown in Figure 11. The rules are standard mostly standard except
we do not allow type abstraction over effect labels – or otherwise equivalence between types cannot
be decided statically. The rules kind-total, kind-row, and kind-arrow are not strictly necessary
and can be derived from kind-app.
A.2 Evaluation Context Typing and Translation
29
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
Γ↑; w↑Fev
⊢ec E↑Fϵ
: σ → σ ′↓| ϵ↑⇝ E′
↓Fev
Γ ;w ⊢ec □ : σ → σ | ϵ ⇝□[cempty]
Γ ;w ⊢ e : σ2 | ϵ ⇝ e′
Γ ;w ⊢ec E : σ1→ (σ2→ϵ σ3) | ϵ ⇝ E′
Γ ;w ⊢ec E e : σ1→ σ3 | ϵ ⇝ E′ w e′[capp1]
Γ ⊢val v : σ2→ϵ σ3 ⇝ v ′
Γ ;w ⊢ec E : σ1→ σ2 | ϵ ⇝ E′
Γ ;w ⊢ec v E : σ1→ σ3 | ϵ ⇝ v ′ w E′[capp2]
Γ ;w ⊢ec E : σ1→ ∀α . σ2 | ϵ ⇝ E′
Γ ;w ⊢ec E [σ ] : σ1→ σ2 [α :=σ ] | ϵ ⇝ E′ [⌈σ ⌉][ctapp]
Γ ⊢ops h : σ | l | ϵ ⇝ h′
Γ ; ⟨⟨l : (m, h′) | w⟩⟩ ⊢ec E : σ1→ σ | ⟨l | ϵ⟩ ⇝ E′
Γ ;w ⊢ec handleϵ h E : σ1→ σ | ϵ ⇝ handlewm h′ E′[chandle]
Fig. 12. Evaluation context typing with evidence translation
B PROOFSThis section contains all the proofs for the Lemmas and Theorems in the main paper organized by
system.
B.1 System Fϵ
B.1.1 Type Erasure.Proof. (Of Lemma 1) By straightforward induction. Note (Λα . v)∗ = v∗ is a value by I.H.. □
Lemma 9. (Substitution of Type Erasure)1. (e[x:=v])∗ = e∗[x:=v∗].2. (v0[x:=v])∗ = v∗
0[x:=v∗].
3. (h[x:=v])∗ = h∗[x:=v∗].
Proof. (Of Lemma 9) Part 1 By induction on e.case e = v0. Follows from Part 2.
case e = e1 e2.
((e1 e2)[x:=v])∗
= ((e1[x:=v]) (e2[x:=v]))∗ by substitution
= (e1[x:=v])∗ (e2[x:=v])∗ by erasure
= (e∗1[x:=v∗]) (e∗
2[x:=v∗]) I.H.
= (e∗1e∗
2) [x:=v] by substitution
= (e1 e2)∗[x:=v] by erasure
30
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
Γ↑;w↑
;w ′↑Fv
⊩ec E↑Fev
: σ → σ ′↓| ϵ↑⇝ e′↓Fv
Γ;w ;w ′ ⊩ec □ : σ → σ | ϵ ⇝ id[mon-cempty]
Γ;w ;w ′ ⊩ e : σ2 | ϵ ⇝ e′
Γ;w ;w ′ ⊩ec E : σ1→ (σ2⇒ ϵ σ3) | ϵ ⇝ g
Γ;w ;w ′ ⊩ec E w e : σ1→ σ3 | ϵ ⇝ (λf . e′ ▷ f w ′) • g[mon-capp1]
Γ;w ;w ′ ⊩ec E : σ1→ ∀α . σ2 | ϵ ⇝ g
Γ;w ;w ′ ⊩ec E [σ ] : σ1→ σ2 [α :=σ ] | ϵ ⇝ (λx . pure (x[⌊σ ⌋])) • g[mon-ctapp]
Γ ⊩val v : σ2⇒ ϵ σ3 ⇝ v ′
Γ;w ;w ′ ⊩ec E : σ1→ σ2 | ϵ ⇝ g
Γ;w ;w ′ ⊩ec v w E : σ1→ σ3 | ϵ ⇝ (v ′ w ′) • g[mon-capp2]
Γ ⊩ops h : σ | l | ϵ ⇝ h′
Γ; ⟨⟨l : (m, h) | w⟩⟩ ; ⟨⟨l : (m, h′) | w ′⟩⟩ ⊩ec E : σ1→ σ | ⟨l | ϵ⟩ ⇝ g
Γ;w ;w ′ ⊩ec handlewm h E : σ1→ σ | ϵ ⇝ prompt[ϵ,σ ] m w ′ ◦ g[mon-chandle]
Fig. 13. Evidence context typing and monadic translation ((▷) is monadic bind, (•) Kleisli composi-
tion, and (◦) is regular function composition).
case e = e1 [σ ].
((e1 [σ ]) [x:=v])∗
= (e1[x:=v] [σ ])∗ by substitution
= (e1[x:=v])∗ by erasure
= e∗1[x:=v∗] I.H.
= (e1 [σ ])∗[x:=v∗] by erasure
case e = handleϵ h e0.
((handleϵ h e0)[x:=v])∗
= (handleϵ h[x:=v] e0[x:=v])∗ by substitution
= handle (h[x:=v])∗ (e0[x:=v])∗ by erasure
= handle (h∗[x:=v∗]) (e∗0[x:=v∗]) Part 3 and I.H.
= (handle h∗ e∗0)[x:=v∗] by substitution
= (handleϵ h e0)∗[x:=v∗] by erasure
Part 2 By induction on v0.
case v0 = x.(x[x:=v])∗
= v∗ by substitution
= x[x:=v∗] by substitution
= x∗[x:=v∗] by erasure
case v0 = y and y , x.
31
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
(y[x:=v])∗
= y∗ by substitution
= y by erasure
= y[x:=v∗] by substitution
= y∗[x:=v∗] by erasure
case v0 = λϵ y :σ . e.((λϵ y :σ . e)[x:=v])∗
= (λϵ y :σ . e[x:=v] )∗ by substitution
= λy. (e[x:=v])∗ by erasure
= λy. e∗[x:=v∗] Part 1
= (λy. e∗)[x:=v∗] by substitution
= (λϵ y : σ . e)∗[x:=v∗] by erasure
case v0 = Λαk . v1.
((Λαk . v1)[x:=v])∗
= (Λαk · v1[x:=v])∗ by substitution
= (v1[x:=v])∗ by erasure
= v∗1[x:=v∗] I.H.
= ( Λαk . v1)∗[x:=v∗] by erasure
case v0 = handlerϵ h.(handlerϵ h[x:=v])∗
= (handlerϵ h[x:=v])∗ by substitution
= handler (h[x:=v])∗ by erasure
= handler h∗[x:=v∗] Part 3
= (handler h∗)[x:=v∗] by substitution
= (handlerϵ h)∗[x:=v∗] by erasure
case v0 = performϵ op σ .((performϵ op σ )[x:=v])∗
= (performϵ op σ )∗ by substitution
= perform op by erasure
= (perform op)[x:=v∗] by substitution
= (performϵ op σ )∗[x:=v∗] by erasure
Part 3 Follows directly from Part 1.
□
Lemma 10. (Type Variable Substitution of Type Erasure)1. (e[α :=σ ])∗ = e∗.2. (v0[α :=σ ])∗ = v∗
0.
3. (h[α :=σ ])∗ = h∗.
Proof. (Of Lemma 10) By straightforward induction. Note all types are erased. □
Proof. (Of Theorem 1) case (λϵ x :σ . e) v −→ e [x:=v].((λϵ x :σ . e) v)∗ = (λx . e∗) v∗ by erasure
v∗ is a value Lemma 1
(λx . e∗) v∗ −→ e∗[x:=v∗] (app)(e[x:=v])∗ = e∗[x:=v∗] Lemma 9
case (Λαk .v) [σ ] −→ v[α :=σ ].
32
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
((Λαk .v) [σ ])∗ = v∗ by erasure
(v[α :=σ ])∗ = v∗ Lemma 10
case (handlerϵ h) v −→ handleϵ h (v ()).((handlerϵ h) v)∗ = handler h∗ v∗ by erasure
v∗ is a value Lemma 1
handler h∗ v∗ −→ handle h∗ (v∗ ()) (handler)case handleϵ h · v −→ v.(handleϵ h · v)∗ = handle h∗ · v∗ by erasure
v∗ is a value Lemma 1
handle h∗ · v∗ −→ v∗ (return)case handleϵ h · E · perform op σ v −→ f [σ ] v k1.
k1 = λϵ x : σ2[α :=σ ]. handleϵ h · E · x (perform)(handleϵ h · E · perform op σ v)∗ = handle h∗ · E∗ · perform op v∗ by erasure
v∗ is a value Lemma 1
handle h∗ · E∗ · perform op v∗ −→ f ∗ v∗ k2 (perform)k2 = λx . handle h∗ · E∗ · x above
k2 = k∗1
by erasure
(f [σ ] v k1)∗ = f ∗ v∗ k2 by erasure
□
B.1.2 Evaluation Context Typing.Proof. (Of Lemma 2) Apply Lemma 16, ignoring all evidence and translations. □
Proof. (Of Lemma 3) Apply Lemma 17, ignoring all evidence and translations. □
Proof. (Of Lemma 4)
∅ ⊢ E[perform op σ v] : σ | ⟨⟩ given
∅ ⊢ perform op σ v : σ1 | ⌈E⌉l Lemma 3
∅ ⊢ perform op σ : σ2→⌈E⌉l σ1 | ⌈E⌉l app
∅ ⊢val perform op σ : σ2→ ⌈E⌉l σ1 val
l ∈ ⌈E⌉l op
E = E1 · handleϵ h · E2 By definition of ⌈E⌉l
op→ f ∈ h above
op ̸∈ bop(E2) Let handleϵ h be the innermost one
□
Proof. (Of Lemma 5)
∅ ⊢ E[perform op σ v] : σ | ϵ given
∅ ⊢ perform op σ v : σ1 | ⟨⌈E⌉l | ϵ⟩ Lemma 3
∅ ⊢ perform op σ : σ2→ ⟨⌈E⌉l | ϵ⟩ σ1 | ⟨⌈E⌉l | ϵ⟩ app
∅ ⊢val perform op σ : σ2→ ⟨⌈E⌉l | ϵ⟩ σ1 val
l ∈ ⟨⌈E⌉l | ϵ⟩ op
op ̸∈ bop(E) given
l ∈ ϵ Follows
□
33
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
B.1.3 Substitution.Lemma 11. (Variable Substitution)If Γ1, x :σ1, Γ2 ⊢ e : σ | ϵ and Γ1, Γ2 ⊢val v : σ1, then Γ1, Γ2 ⊢ e[x:=v] : σ | ϵ .
Proof. (Of Lemma 11) Applying Lemma 18, ignoring all evidences and translations. □
Lemma 12. (Type Variable Substitution)If Γ ⊢ e : σ | ϵ and⊢wf σ1 : k, then Γ[αk
:=σ1] ⊢ e[αk:=σ1] : σ [αk
:=σ1] | ϵ .
Proof. (Of Lemma 12) Applying Lemma 20, ignoring all evidences and translations. □
B.1.4 Progress.Lemma 13. (Progress with effects)If ∅ ⊢ e1 : σ | ϵ then either e1 is a value, or e1 7−→ e2, or e1 = E[perform op σ v],where op : ∀α . σ1→ σ2 ∈ Σ(l), and l ̸∈ bop(E).
Proof. (of Lemma 13) By induction on typing. case e1 = v. The goal holds trivially.case e1 = e3 e4.
∅ ⊢ e3 e4 : σ | ϵ given
∅ ⊢ e3 : σ1→ϵ σ | ϵ app
∅ ⊢ e4 : σ1 | ϵ above
By I.H., we know that either e3 is a value, or e3 7−→e5, or e3 = E0[perform op σ v].• e3 7−→ e5. Then we know e3 e4 7−→ e5 e4 by step and the goal holds.
• e3 = E0[perform op σ v]. Let E = E0 e4, then we have e1 = E[perform op σ v].• e3 is a value. By I.H., we know either e4 is a value, or e4 7−→ e6, or e4 = E0[perform op σ v]– e4 7−→ e6, then we know e3 e4 7−→ e3 e6 by step and the goal holds.
– e4 = E0[perform op σ v]. Let E = e3 E0, then we have e1 = E[perform op σ v].– e4 is a value, then we do case analysis on the form of e3.
subcase e3 = x. This is impossible because x is not well-typed under an empty context.
subcase e3 = λx : σ . e. Then by (app) and (step) we have (λx : σ · e) e4 7−→ e[x:=e4].
subcase e3 = Λα . e. This is impossible because it does not have a function type.
subcase e3 = perform op σ . Let E = □, then we have e1 = E[perform op σ e4].
subcase e3 = handlerϵ h. Then by (handler) and (step) we havehandlerϵ h e4 −→ handleϵ h (e4 ()).
case e1 = e3 [σ1].
∅ ⊢ e3 [σ1] : σ2[α :=σ1] | ϵ given
∅ ⊢ e3 : ∀α . σ2 | ϵ app
By I.H., we know that either e3 is a value, or e3 7−→e5, or e3 = E0[perform op σ v].• e3 7−→ e5. Then we know e3 [σ1] 7−→ e5 [σ1] by step and the goal holds.
• e3 = E0[perform op σ v]. Let E = E0 [σ1], then we have e1 = E[perform op σ v].• e3 is a value. Then we do case analysis on the form of e3.
subcase e3 = x. This is impossible because x is not well-typed under an empty context.
subcase e3 = λx : σ . e. This is impossible because it does not have a polymorphic type.
subcase e3 = Λα . e. Then by (tapp) and (step) we have (Λα . e) [σ1] 7−→ e[α :=σ1].
subcase e3 = perform op σ ′. This is impossible because it does not have a polymorphic type.
subcase e3 = handlerϵ h. This is impossible because it does not have a polymorphic type.
case e1 = handleϵ h e.
34
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
∅ ⊢ handleϵ h e : σ | ϵ given
∅ ⊢ e : σ | ⟨l | ϵ⟩ handle
By I.H., we know that either e is a value, or e 7−→e3, or e = E0[perform op σ v].• e 7−→ e3. Then we know handleϵ h e 7−→ handleϵ h e3 by step and the goal holds.
• e = E0[perform op σ v], and op ̸∈ bop(E0). We discuss whether op is bound in h.– op→ f ∈ h. Then by (perform) and (step)wehave handleϵ h · E0 · perform op σ v 7−→ f σ v k.– op ̸∈ h. Let E = handleϵ h E0, then we have e1 = E[perform op σ v].• e is a value. Then by (return) and (step) we have handleϵ h e 7−→ e.□
Proof. (Of Theorem 2) Apply Lemma 13, then we know that either e1 is a value, or e1 7−→ e2, or
e1 = E[perform op σ v], where op : ∀α . σ1→ σ2 ∈ Σ(l), and l ̸∈ bop(E). For the first two cases,
we have proved the goal. For the last case, we prove it by contradiction.
∅ ⊢ E[perform op σ v] : σ | ⟨⟩ given
l ̸∈ bop(E) given
l ∈ ⟨⟩ Lemma 5
Contradiction
□
B.1.5 Preservation.Lemma 14. (Small Step Preservation)If ∅ ⊢ e1 : σ | ϵ and e1 −→ e2, then ∅ ⊢ e2 : σ | ϵ .
Proof. (of Lemma 14) By induction on reduction.
case (λϵ x :σ1. e) v −→ e[x:=v].∅ ⊢ (λϵ x :σ1. e) v : σ2 | ϵ given
∅ ⊢ λϵ x :σ1. e : σ1→ ϵ σ2 | ϵ app
∅ ⊢ v : σ1 | ϵ above
x :σ1 ⊢ e : σ2 | ϵ abs
∅ ⊢ e[x:=v] : σ2 | ϵ Lemma 11
case (Λα . v) [σ ] −→ v[α :=σ ].
∅ ⊢ (Λα . v) [σ ] : σ1 [α :=σ ] | ϵ given
∅ ⊢ Λα . v : ∀α . σ1 | ϵ tapp
∅ ⊢val Λα . v : ∀α . σ1 val
∅ ⊢val v : σ1 tabs
∅⊢val v : σ1 | ϵ val
∅⊢val v[α :=σ ] : σ1[α :=σ ] | ϵ Lemma 12
case (handlerϵ h) v −→ handleϵ h (v ()).
35
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
∅ ⊢ (handlerϵ h) v : σ | ϵ given
∅ ⊢ handlerϵ h : (() → ⟨l | ϵ⟩ σ ) → ϵ σ | ϵ app
∅ ⊢ v : () → ⟨l | ϵ⟩ σ | ϵ above
∅ ⊢val handlerϵ h : (() → ⟨l | ϵ⟩ σ ) → ϵ σ val
∅ ⊢ops h : σ | l | ϵ handler
∅ ⊢ v : () → ⟨l | ϵ⟩ σ | ⟨l | ϵ⟩ Lemma 25
∅ ⊢ v () : σ | ⟨l | ϵ⟩ app
∅ ⊢ handleϵ h (v ()) : σ | ⟨ϵ⟩ handle
case handleϵ h · v −→ v.∅ ⊢ handleϵ h · v : σ | ϵ given
∅ ⊢ v : σ | ⟨l | ϵ⟩ handle
∅ ⊢ v : σ | ⟨ϵ⟩ Lemma 25
case handleϵ h · E · perform op σ v −→ f [σ ] v k.op ̸∈ bop(E) and op→ f ∈ h given
op : ∀α . σ1→ σ2 ∈ Σ(l) given
k = λϵ x : σ2[α :=σ ]. handleϵ h · E · x given
∅ ⊢ handleϵ h · E · perform op σ v : σ | ϵ given
∅ ⊢ops h : σ | l | ϵ handle
∅ ⊢val f : ∀α . σ1→ ϵ (σ2→ ϵ σ ) → ϵ σ ops
∅ ⊢ f : ∀α . σ1→ ϵ (σ2→ ϵ σ ) → ϵ σ | ϵ val
∅ ⊢ f [σ ] : σ1[α :=σ ] → ϵ (σ2[α :=σ ] → ϵ σ ) → ϵ σ | ϵ tapp
∅ ⊢ perform op σ v : σ2[α :=σ ] | ⟨⌈handleϵ h E⌉l | ϵ⟩ Lemma 3
∅ ⊢ec handleϵ h · E : σ2[α :=σ ] → σ | ϵ above
∅ ⊢ v : σ1[α := σ ] | ⟨⌈handleϵ h E⌉l | ϵ⟩ app and tapp
∅ ⊢ v : σ1[α := σ ] | ϵ Lemma 25
∅ ⊢ f [σ ] v : (σ2[α :=σ ] → ϵ σ ) → ϵ σ | ϵ app
x :σ2[α :=σ ] ⊢val x : σ2[α :=σ ] var
x :σ2[α :=σ ] ⊢ x : σ2[α :=σ ] | ϵ val
x :σ2[α :=σ ] ⊢ec handleϵ · E : σ2[α :=σ ] → σ | ϵ weakening
x :σ2[α :=σ ] ⊢ handleϵ h · E · x : σ | ϵ Lemma 2
∅ ⊢val λϵ x : σ2[α :=σ ]. handleϵ h · E · x : σ2[α :=σ ] → ϵ σ abs
∅ ⊢ λϵ x : σ2[α :=σ ]. handleϵ h · E · x : σ2[α :=σ ] → ϵ σ | ϵ val
∅ ⊢ f [σ ] v k : σ | ϵ app
□
Proof. (Of Theorem 3)
e1 = E[e′1] (step)
e′1−→ e′
2above
e2 = E[e′2] above
∅ ⊢ E[e′1] : σ | ⟨⟩ given
∅ ⊢ e1 : σ1 | ⌈E⌉l Lemma 3
∅ ⊢ E : σ1→ σ | ⟨⟩ above
∅ ⊢ e2 : σ1 | ⌈E⌉l Lemma 14
∅ ⊢ E[e2] : σ | ⟨⟩ Lemma 2
□
36
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
B.2 Translation from System Fϵ to System Fev
B.2.1 Type Translation.Lemma 15. (Stable under substitution)Translation is stable under substitution, ⌈σ ⌉[α := ⌈σ ′⌉] = ⌈σ [α :=σ ′]⌉.
Proof. (Of Lemma 15) By induction on σ .case σ = α .⌈α⌉[α :=⌈σ ′⌉]= α[α :=⌈σ ′⌉] by translation
= ⌈σ ′⌉ by substitution
⌈α[α :=σ ′]⌉= ⌈σ ′⌉ by substitution
case σ = β and β , α .
⌈β⌉[α :=⌈σ ′⌉]= β[α :=⌈σ ′⌉] by translation
= β by substitution
⌈β[α :=σ ′]⌉= ⌈β⌉ by substitution
= β by translation
case σ = σ1→ ϵ σ2.
⌈σ1→ ϵ σ2⌉[α :=⌈σ ′⌉]= (⌈σ1⌉ ⇒ ϵ ⌈σ2⌉)[α :=⌈σ ′⌉] by translation
= (⌈σ1⌉[α :=⌈σ ′⌉])⇒ ϵ (⌈σ2⌉[α :=⌈σ ′⌉]) by substitution
= (⌈σ1[α :=σ ′]⌉)⇒ ϵ (⌈σ2[α :=σ ′]⌉) I.H.
⌈(σ1→ ϵ σ2)[α :=σ ′]⌉= ⌈σ1[α :=σ ′]→ϵ σ2[α :=σ ′]⌉ by substitution
= (⌈σ1[α :=σ ′]⌉)⇒ ϵ (⌈σ2[α :=σ ′]⌉) by translation
case σ = ∀β . σ1.
⌈∀β . σ1⌉[α :=⌈σ ′⌉]= (∀β . ⌈σ1⌉)[α :=⌈σ ′⌉] by translation
= ∀β . ⌈σ1⌉[α :=⌈σ ′⌉] by substitution
= ∀β . ⌈σ1[α :=σ ′]⌉ I.H.
⌈(∀β . σ1)[α :=σ ′]⌉= ⌈∀β . σ1[α :=σ ′]⌉ by substitution
= ∀β . ⌈σ1[α :=σ ′]⌉ by translation
case σ = c τ1 . . . τn.
⌈c τ1 . . . τn⌉[α :=⌈σ ′⌉]= (c ⌈τ1⌉ . . . ⌈τn⌉)[α :=⌈σ ′⌉] by translation
= c (⌈τ1⌉[α :=⌈σ ′⌉]) . . . (⌈τn⌉[α :=⌈σ ′⌉]) by substitution
= c (⌈τ1[α :=σ ′]⌉) . . . (⌈τn[α :=σ ′]⌉) by I.H.
⌈(c τ1 . . . τn)[α :=σ ′]⌉= ⌈c τ1[α :=σ ′] . . . τn[α :=σ ′]⌉ by substitution
= c (⌈τ1[α :=σ ′]⌉) . . . (⌈τn[α :=σ ′]⌉) by translation
□
B.2.2 Evaluation Context Typing.
37
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
Lemma 16. (Evaluation context typing with evidence translation)If Γ; w ⊢ec E : σ1→ σ2 | ϵ ⇝ E′ and Γ; ⟨⟨⌈E′⌉ | w⟩⟩ ⊢ e : σ1 | ⟨⌈E′⌉l | ϵ⟩ ⇝ e′ ,then Γ; w ⊢ E[e] : σ2 | ϵ ⇝ E′[e′].
Proof. (of Lemma 16) By induction on the evaluation context typing.
case E = □. The goal follows trivially.case E = E0 e0.
Γ;w ⊢ec E0 e0 : σ1→ σ2 | ϵ ⇝ E′0w e′
0given
Γ;w ⊢ec E0 : σ1→ (σ3→ϵ σ2) | ϵ ⇝ E′0
capp1
Γ;w ⊢ e0 : σ3 | ϵ ⇝ e′0
above
⌈E′0w e′
0⌉ = ⌈E′
0⌉ by definition
⌈E′0w e′
0⌉l = ⌈E′
0⌉l by definition
Γ; ⟨⟨⌈E′0w e0⌉ | w⟩⟩ ⊢ e : σ1 | ⟨⌈E′0 w e′⌉l | ϵ⟩ ⇝ e′ given
Γ; ⟨⟨⌈E′0⌉ | w⟩⟩ ⊢ e : σ1 | ⟨⌈E′0⌉
l | ϵ⟩ ⇝ e′ by substitution
Γ;w ⊢ E0[e] : σ3→ϵ σ2 | ϵ ⇝ E′0[e′] I.H.
Γ;w ⊢ E0[e] e0 : σ2 | ϵ ⇝ E′0[e] w e′
0app
case E = v E0.
Γ;w ⊢ec v E0 : σ1→ σ2 | ϵ ⇝ v ′ w E′0
given
Γ ⊢val v : σ3→ϵ σ2 ⇝ v ′ capp2
Γ;w ⊢ec E0 : σ1→ σ3 | ϵ ⇝ E′0
above
⌈v ′ w E′0⌉ = ⌈E′
0⌉ by definition
⌈v w E′0⌉l = ⌈E′
0⌉l by definition
Γ; ⟨⟨⌈v w E′0⌉ | w⟩⟩ ⊢ e : σ1 | ⟨⌈v w E′
0⌉l | ϵ⟩ ⇝ e′ given
Γ; ⟨⟨⌈E′0⌉ | w⟩⟩ ⊢ e : σ1 | ⟨⌈E′0⌉
l | ϵ⟩ ⇝ e′ by substitution
Γ;w ⊢ E0[e] : σ3 | ϵ ⇝ E′[e′] I.H.
Γ;w ⊢ v E0[e] : σ2 | ϵ ⇝ v ′ w ′ E′0[e′] app
case E = E0 [σ ].
Γ;w ⊢ec E0 [σ ] : σ1→ σ3[α :=σ ] | ϵ ⇝ E′0[⌈σ ⌉] given
Γ;w ⊢ec E0 : σ1→ ∀α . σ3 | ϵ ⇝ E′0
ctapp
⌈E′0[⌈σ ⌉]⌉ = ⌈E′
0⌉ by definition
⌈E′0[⌈σ ⌉]⌉l = ⌈E′
0⌉l by definition
Γ; ⟨⟨⌈E′0[⌈σ ⌉]⌉ | w⟩⟩ ⊢ e : σ1 | ⟨⌈E′0 [⌈σ ⌉] ⌉
l | ϵ⟩ ⇝ e′ given
Γ; ⟨⟨⌈E′0⌉ | w⟩⟩ ⊢ e : σ1 | ⟨⌈E′0⌉
l | ϵ⟩ ⇝ e′ by substitution
Γ;w ⊢ E0[e] : ∀α . σ3 | ϵ ⇝ E′0[e′] I.H.
Γ;w ⊢ E0[e] [σ ] : σ3[α :=σ ] ⇝ E′0[e′] [⌈σ ⌉] | ϵ tapp
case E = handlew h E0.
Γ;w ⊢ec handlew h E0 : σ1→ σ2 | ϵ ⇝ handlewm h′ E′0
given
Γ; ⟨⟨l : (m, h) | w⟩⟩ ⊢ec E0 : σ1→ σ2 | ⟨l | ϵ⟩ chandle
Γ ⊢ops h : σ | l | ϵ ⇝ h′ above
Γ; ⟨⟨⌈handlewm h E′0⌉ | w⟩⟩ ⊢ e : σ1 | ⟨⌈handlewm h E′
0⌉l | ϵ⟩ ⇝ e′ given
Γ; ⟨⟨⌈E′0⌉ | ⟨⟨l : (m, h) | w⟩⟩⟩⟩ ⊢ e : σ1 | ⟨⌈E′0⌉
l | l | ϵ⟩ ⇝ e′ by definition
Γ; ⟨⟨l : (m, h) | w⟩⟩ ⊢ec E0[e] : σ2 | ⟨l | ϵ⟩ ⇝ E′0[e′] I.H.
Γ;w ⊢ handlew h E0[e] : σ2 | ϵ ⇝ handlewm h′ E′0[e′] handle
□
38
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
Lemma 17. (Translation evidence corresponds to the evalution context)If ∅; w ⊢ E[e] : σ | ϵ ⇝ e1 then there exists σ1, E′, e′ such that
∅; w ⊢ec E : σ1→ σ | ϵ ⇝ E′, and ∅; ⟨⟨⌈E′⌉ | w⟩⟩ ⊢ e : σ1 | ⟨⌈E′⌉l | ϵ⟩ ⇝ e′, and e1 = E′[e′] .
Proof. (Of Lemma 17) Induction on E.case E = □. Let σ1 = σ , E′ = □, e′ = e1 and the goal holds trivially.
case E = E0 e0.
∅;w ⊢ E0[e] e0 : σ | ϵ ⇝ e2 w e3 given
∅;w ⊢ E0[e] : σ2→ϵ σ | ϵ ⇝ e2 app
∅;w ⊢ e0 : σ2 | ϵ ⇝ e3 above
∅;w ⊢ec E0 : σ1→ (σ2→ϵ σ ) | ϵ ⇝ E′0
I.H.
∅;w ⊢ec E0 e0 : σ1→ σ | ϵ ⇝ E′0w e3 capp1
∅; ⟨⟨⌈E′0⌉ | w⟩⟩ ⊢ e : σ1 | ⟨⌈E′0⌉
l | ϵ⟩ ⇝ e′ I.H.
e2 = E′0[e′] I.H.
⌈E′0w e3⌉ = ⌈E′0⌉ by definition
⌈E′0w e3⌉
l = ⌈E′0⌉l by definition
∅; ⟨⟨⌈E′0w e3⌉ | w⟩⟩ ⊢ e : σ1 | ⟨⌈E′0 w e3⌉
l | ϵ⟩ ⇝ e′ by substitution
E′ = E′0w e3 Let
case E = v E0.
∅;w ⊢ v E0[e] : σ | ϵ ⇝ e2 w e3 given
∅;w ⊢ v : σ2→ϵ σ | ϵ ⇝ e2 app
∅;w ⊢ E0[e] : σ2 | ϵ ⇝ e3 above
∅;w ⊢ec E0 : σ1→ σ2 | ϵ ⇝ E′0
I.H.
∅;w ⊢ec v E0 : σ1→ σ | ϵ ⇝ e2 w E′0
capp2
∅; ⟨⟨⌈E0⌉ | w⟩⟩ ⊢ e : σ1 | ⟨⌈E′0⌉l | ϵ⟩ ⇝ e′ I.H.
e3 = E′0[e′] I.H.
⌈e2 w E0⌉ = ⌈E0⌉ by definition
⌈e2 w E0⌉l = ⌈E0⌉
lby definition
∅; ⟨⟨⌈e2 w E0⌉ | w⟩⟩ ⊢ e : σ1 | ⟨⌈E⌉l | ϵ⟩ ⇝ e′ by substitution
E′ = e2 w E′0
Let
case E = E0 [σ0].
∅;w ⊢ E0[e] [σ0] : σ2[α :=σ0] | ϵ ⇝ e2 [⌈σ0⌉] given
∅;w ⊢ E0[e] : ∀α · σ2 | ϵ ⇝ e2 tapp
∅;w ⊢ec E0 : σ1→ (∀α . σ2) | ϵ ⇝ E′0
I.H.
∅;w ⊢ec E0 [σ0] : σ1→ σ2[α :=σ0] | ϵ ⇝ E′0[⌈σ0⌉] ctapp
∅; ⟨⟨⌈E′0⌉ | w⟩⟩ ⊢ e : σ1 | ⟨⌈E′0⌉
l | ϵ⟩ ⇝ e′ I.H.
e2 = E′0[e′] I.H.
⌈E′0[σ0]⌉ = ⌈E′0⌉ by definition
⌈E′0[σ0]⌉
l = ⌈E′0⌉l by definition
∅; ⟨⟨⌈E′0[σ0]⌉ | w⟩⟩ ⊢ e : σ1 | ⟨⌈E⌉l | ϵ⟩ ⇝ e′ by substitution
E′ = E′0[⌈σ0⌉] Let
case E = handle h E0.
39
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
∅;w ⊢ handle h E0[e] : σ | ϵ ⇝ handlewm h′ e2 given
∅; ⟨⟨l : (m, h′) | w⟩⟩ ⊢ E0[e] : σ | ⟨l | ϵ⟩ ⇝ e2 handle
∅; ⟨⟨l : (m, h′) | w⟩⟩ ⊢ec E0 : σ1→ σ | ⟨l | ϵ⟩ ⇝ E′0
I.H.
∅;w ⊢ec handle h E0 : σ1→ σ | ϵ ⇝ handlewm h′ E′0
chandle
∅; ⟨⟨⌈E′0⌉ | ⟨⟨l : (m, h′) | w⟩⟩⟩⟩ ⊢ e : σ1 | ⟨⌈E′0⌉
l | l | ϵ⟩ ⇝ e′ I.H.
e2 = E′0[e′] I.H.
⟨⟨⌈E′0⌉ | ⟨⟨l : (m, h′) | w⟩⟩⟩⟩ = ⟨⟨⌈E′
0⌉ | ⟨⟨⟨⟨l : (m, h′)⟩⟩ | w⟩⟩⟩⟩ by definition
⟨⟨⌈E′0⌉ | ⟨⟨⟨⟨l : (m, h′)⟩⟩ | w⟩⟩⟩⟩ = ⟨⟨⌈handlewm h′ · E′
0⌉ | w⟩⟩ by definition
⌈handlewm h′ E′0⌉l = ⟨⌈E′
0⌉l | l⟩ by definition
∅; ⟨⟨⌈handlewm h′ · E′0⌉ | w⟩⟩ ⊢ e : σ1 | ⟨⌈E′⌉l | ϵ⟩ ⇝ e′ by substitution
E′ = handlewm h′ E′0
Let
□
B.2.3 Substitution.Lemma 18. (Translation Variable Substitution)1. If Γ1, x :σ1, Γ2;w ⊢ e : σ | ϵ ⇝ e′, and Γ1, Γ2 ⊢val v : σ1 ⇝ v ′,then Γ1, Γ2 ;w[x:=v ′] ⊢ e[x:=v] : σ | ϵ ⇝ e′[x:=v ′].2. If Γ1, x :σ1, Γ2;w ⊢val v0 : σ ⇝ v ′
0, and Γ1, Γ2 ⊢val v : σ1 ⇝ v ′,
then Γ1, Γ2 ⊢val v[x:=v] : σ ⇝ v ′0[x:=v ′].
3. If Γ1, x :σ1, Γ2 ⊢ops h : σ | l ⇝ h′, and Γ1, Γ2 ⊢val v : σ1 ⇝ v ′,then Γ1, Γ2 ⊢ops h[x:=v] : σ | l ⇝ h′[x:=v ′].
Proof. (Of Lemma 18)
Part 1 By induction on translation.
case e = v0.
Γ1, x :σ1, Γ2;w ⊢ v0 : σ | ϵ ⇝ v ′0
given
Γ1, x :σ1, Γ2 ⊢val v0 : σ ⇝ v ′0
var
Γ1, Γ2 ⊢val v0[x:=v] : σ ⇝ v ′0[x:=v ′] Part 2
Γ1, Γ2;w[x:=v] ⊢ v0[x:=v] : σ | ϵ ⇝ v ′0[x:=v ′] var
case e = e1 e2.
Γ1, x :σ1, Γ2;w ⊢ e1 e2 : σ | ϵ ⇝ e′1w e′
2given
Γ1, x :σ1, Γ2;w ⊢ e1 : σ1→ ϵ σ | ϵ ⇝ e′1
app
Γ1, x :σ1, Γ2;w ⊢ e2 : σ1 | ϵ ⇝ e′1
app
Γ1, Γ2;w[x:=v ′] ⊢ e1[x:=v] : σ1→ ϵ σ | ϵ ⇝ e′1[x:=v ′] I.H.
Γ1, Γ2;w[x:=v ′] ⊢ e2[x:=v] : σ1 | ϵ ⇝ e′2[x:=v ′] I.H.
Γ1, Γ2;w[x:=v ′] ⊢ e1[x:=v] e2[x:=v] : σ | ϵ ⇝ e′1[x:=v ′] w[x:=v ′] e′
2[x:=v ′] app
case e = e1 [σ ].
Γ1, x :σ1, Γ2;w ⊢ e1 [σ ] : σ1[α :=σ ] | ϵ ⇝ e′1[⌈σ ⌉] given
Γ1, x :σ1, Γ2;w ⊢ e1 : ∀α . σ1 | ϵ ⇝ e′1
tapp
Γ1, Γ2;w[x:=v ′] ⊢ e1[x:=v] : ∀α . σ1 | ϵ ⇝ e′1[x:=v ′] I.H.
Γ1, Γ2;w[x:=v ′] ⊢ e1[x:=v] [σ ] : σ1[α :=σ ] | ϵ ⇝ e′1[x:=v ′] [⌈σ ⌉] tapp
case e = handleϵ h e.
40
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
Γ1, x :σ1, Γ2;w ⊢ handleϵ h e : σ | ϵ ⇝ handlewm h′ e′ given
Γ1, x :σ1, Γ2 ⊢ops h : σ | l | ϵ ⇝ h′ handle
Γ1, x :σ1, Γ2; ⟨⟨l : (m, h′) | w⟩⟩ ⊢ e : σ | ⟨l | ϵ⟩ ⇝ e′ above
Γ1, Γ2 ⊢ops h[x:=v] : σ | l | ϵ ⇝ h′[x:=v ′] Part 3
Γ1, Γ2; ⟨⟨l : (m, h′[x:=v ′]) | w[x:=v ′]⟩⟩ ⊢ e[x:=v] : σ | ⟨l | ϵ⟩ ⇝ e′[x:=v ′] I.H.
Γ1, Γ2; w[x:=v ′] ⊢ handleϵ h[x:=v] e[x:=v] : σ | ⟨l | ϵ⟩ ⇝ handlewm h′[x:=v ′] e′[x:=v ′] handle
Part 2 By induction on translation.
case v0 = x.Γ1, x :σ1, Γ2 ⊢val x : σ1 ⇝ x given
x[x:=v] = v by substitution
x[x:=v ′] = v ′ by substitution
Γ1, Γ2 ⊢val v : σ1 ⇝ v ′ given
Γ1, Γ2 ⊢val x[x:=v] : σ1 ⇝ x[x:=v ′] follows
case v0 = y and y , x.Γ1, x :σ1, Γ2 ⊢val y : σ ⇝ y given
y :σ ∈ Γ1, x :σ1, Γ2 var
y , x given
y :σ ∈ Γ1, Γ2 follows
Γ1, Γ2 ⊢val y : σ ⇝ y var
y[x:=v] = y by substitution
y[x:=v ′] = y by substitution
Γ1, Γ2 ⊢val y[x:=v] : σ ⇝ y[x:=v ′] var
case v0 = λϵ yσ2 . e.Γ1, x :σ1, Γ2 ⊢val λϵ yσ2 . e : σ2→ σ3 ⇝ λϵ z : evv ϵ, y : ⌈σ2⌉ . e′ given
Γ1, x :σ1, Γ2, y :σ2; z ⊢ e : σ3 | ϵ ⇝ e′ abs
Γ1, Γ2, y :σ2; z ⊢ e[x:=v] : σ3 | ϵ ⇝ e′[x:=v ′] Part 1
Γ1, Γ2 ⊢val λϵ yσ2 . e[x:=v] : σ2→ σ3 ⇝ λϵ z : evv ϵ, y : ⌈σ2⌉ . e′[x:=v ′] abs
case v0 = Λαk . v1.
Γ1, x :σ1, Γ2 ⊢val Λαk . v1 : ∀αk . σ2 ⇝ Λαk . v ′1
given
Γ1, x :σ1, Γ2 ⊢val v1 : σ2 ⇝ v ′1
tabs
Γ1, Γ2 ⊢val v1[x:=v] : σ2 ⇝ v ′1[x:=v ′] I.H.
Γ1, Γ2 ⊢val Λαk . v1[x:=v] : ∀αk . σ2 ⇝ Λαk . v ′1[x:=v ′] tabs
case v0 = perform op σ .Γ1, x :σ1, Γ2 ⊢val perform op σ : σ2[α :=σ ] → σ3[α :=σ ] ⇝ perform op ⌈σ ⌉ given
op : ∀α . σ1→ σ2 ∈ Σ(l) perform
(perform op σ )[x:=v] = perform op σ by substitution
(perform op ⌈σ ⌉)[x:=v ′] = perform op ⌈σ ⌉ by substitution
Γ1, Γ2 ⊢val (perform op σ )[x:=v] : σ2[α :=σ ] → σ3[α :=σ ] perform
⇝ (perform op ⌈σ ⌉)[x:=v ′]case v0 = handlerϵ h.
Γ1, x :σ1, Γ2 ⊢val handlerϵ h : σ ⇝ handlerwm h′ given
Γ1, x :σ1, Γ2 ⊢ops h : σ | l | ϵ ⇝ h′ handler
Γ1, Γ2 ⊢ops h[x:=v] : σ | l | ϵ ⇝ h′[x:=v ′] Part 3
Γ1, Γ2 ⊢val handlerϵ h[x:=v] : σ ⇝ handlerwm h′[x:=v ′] handler
Part 3 Follows directly from Part 2.
□
41
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
Lemma 19. (Translation Evidence Variable Substitution)If Γ;w ⊢ e : σ | ϵ ⇝ e′ and z ̸∈ Γ, then Γ;w[z:=w1] ⊢ e : σ | ϵ ⇝ e′[z:=w1].
Proof. (Of Lemma 19) By induction on the typing.
case e = v0.
Γ;w ⊢ v : σ | ϵ ⇝ v ′ given
Γ ⊢val v : σ ⇝ v ′ var
z ̸∈ Γ given
v ′[z:=w1] = v ′ z out of scope of v ′
Γ;w[z:=w1] ⊢ v : σ | ϵ ⇝ v ′ Lemma 25
case e = e1 e2.
Γ;w ⊢ e1 e2 : σ | ϵ ⇝ e′1w e′
2given
Γ;w ⊢ e1 : σ1→ ϵ σ | ϵ ⇝ e′1
app
Γ;w ⊢ e2 : σ1 | ϵ ⇝ e′1
app
Γ;w[z:=w1] ⊢ e1 : σ1→ ϵ σ | ϵ ⇝ e′1[z:=w1] I.H.
Γ;w[z:=w1] ⊢ e2 : σ1 | ϵ ⇝ e′2[z:=w1] I.H.
Γ;w[z:=w1] ⊢ e1 e2 : σ | ϵ ⇝ e′1[z:=w1] w[z:=w1] e′2[z:=w1] app
case e = e1 [σ ].
Γ;w ⊢ e1 [σ ] : σ1[α :=σ ] | ϵ ⇝ e′1[⌈σ ⌉] given
Γ;w ⊢ e1 : ∀α . σ1 | ϵ ⇝ e′1
tapp
Γ;w[z:=w1] ⊢ e1 : ∀α . σ1 | ϵ ⇝ e′1[z:=w1] I.H.
Γ;w[z:=w1] ⊢ e1 [σ ] : σ1[α :=σ ] | ϵ ⇝ e′1[z:=w1] [⌈σ ⌉] tapp
case e = handleϵ h e.Γ;w ⊢ handleϵ h e : σ | ϵ ⇝ handlewm h′ e′ given
Γ ⊢ops h : σ | l | ϵ ⇝ h′ handle
Γ; ⟨⟨l : (m, h′) | w⟩⟩ ⊢ e : σ | ⟨l | ϵ⟩ ⇝ e′ above
v ̸∈ Γ given
h′[z:=w] = h′ z out of scope of z′
Γ; ⟨⟨l : (m, h′[z:=w]) | w[x:=v ′]⟩⟩ ⊢ e : σ | ⟨l | ϵ⟩ ⇝ e′[z:=w] I.H.
Γ; ⟨⟨l : (m, h′) | w[x:=v ′]⟩⟩ ⊢ e : σ | ⟨l | ϵ⟩ ⇝ e′[z:=w] namely
Γ; w[x:=v ′] ⊢ handleϵ h e : σ | ⟨l | ϵ⟩ ⇝ handlewm h′ e′[x:=v ′] handle
□
Lemma 20. (Translation Type Variable Substitution)1. If Γ;w ⊢ e : σ | ϵ ⇝ e′ and⊢wf σ1 : k,then Γ[αk
:=σ1];w[αk:=⌈σ1⌉] ⊢ e[αk
:=σ1] : σ [αk:=σ1] | ϵ ⇝ e′[αk
:=⌈σ1⌉].
2. If Γ ⊢val v : σ ⇝ v ′ and⊢wf σ1 : k,then Γ[αk
:=σ1] ⊢val v[αk:=σ1] : σ [αk
:=σ1] ⇝ v ′[αk:=⌈σ1⌉].
3. If Γ ⊢ops h : σ | l | ϵ ⇝ h′ and⊢wf σ1 : k,then Γ[αk
:=σ1] ⊢ops h[αk:=σ1] : σ [αk
:=σ1] | l | ϵ ⇝ v ′[αk:=⌈σ1⌉].
Proof. (Of Lemma 20) Part 1 By induction on translation.
case e = v0.
Γ;w ⊢ v0 : σ | ϵ ⇝ v ′0
given
Γ ⊢val v0 : σ ⇝ v ′0
var
Γ[αk:=σ1] ⊢val v0[α
k:=σ1] : σ [αk
:=σ1] ⇝ v ′0[αk
:=⌈σ1⌉] Part 2
Γ[αk:=σ1];w[αk
:=⌈σ1⌉] ⊢ v0[αk:=σ1] : σ [αk
:=σ1] | ϵ ⇝ v ′0[αk
:=⌈σ1⌉] var
case e = e1 e2.
42
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
Γ;w ⊢ e1 e2 : σ | ϵ ⇝ e′1w e′
2given
Γ;w ⊢ e1 : σ1→ ϵ σ | ϵ ⇝ e′1
app
Γ;w ⊢ e2 : σ1 | ϵ ⇝ e′1
app
Γ[αk:=σ1];w[αk
:=⌈σ1⌉] ⊢ e1[αk:=σ1] : σ1[α
k:=σ1] → ϵ σ [αk
:=σ1] | ϵ ⇝ e′1[αk
:=⌈σ1⌉] I.H.
Γ[αk:=σ1];w[αk
:=⌈σ1⌉] ⊢ e2[αk:=σ1] : σ1[α
k:=σ1] | ϵ ⇝ e′
2[αk
:=⌈σ1⌉] I.H.
Γ[αk:=σ1];w[αk
:=⌈σ1⌉] ⊢ e1[αk:=σ1] e2[α
k:=σ1] : σ [αk
:=⌈σ1⌉] | ϵ app
⇝ e′1[αk
:=⌈σ1⌉] w[αk:=⌈σ1⌉] e′2[α
k:=⌈σ1⌉]
case e = e1 [σ ].
Γ;w ⊢ e1 [σ ] : σ2[β :=σ ] | ϵ ⇝ e′1[⌈σ ⌉] given
Γ;w ⊢ e1 : ∀β . σ2 | ϵ ⇝ e′1
tapp
Γ[αk:=σ1];w[αk
:=⌈σ1⌉] ⊢ e1[αk:=σ1] : ∀β . σ2[α
k:=σ1] | ϵ ⇝ e′
1[αk
:=⌈σ1⌉] I.H.
Γ[αk:=σ1];w[αk
:=⌈σ1⌉] ⊢ e1[αk:=σ1] [σ [α
k:=σ1] ] : (σ2[α
k:=σ1])[β :=σ ] | ϵ tapp
⇝ e′1[αk
:=⌈σ1⌉] [⌈σ [αk:=σ1]⌉]
(σ2[αk:=σ1])[β :=σ ]
= (σ2[β :=σ ])[αk:=(σ1[β :=σ ])] by substitution
= (σ2[β :=σ ])[αk:=σ1] β fresh to σ1
Γ[αk:=σ1];w[αk
:=⌈σ1⌉] ⊢ e1[αk:=σ1] [σ [α
k:=σ1] ] : (σ2[β :=σ ])[αk
:=σ1] | ϵ therefore
⇝ e′1[αk
:=⌈σ1⌉] [⌈σ [αk:=σ1]⌉]
case e = handleϵ h e.Γ;w ⊢ handleϵ h e : σ | ϵ ⇝ handlewm h′ e′ given
Γ ⊢ops h : σ | l | ϵ ⇝ h′ handle
Γ; ⟨⟨l : (m, h′) | w⟩⟩ ⊢ e : σ | ⟨l | ϵ⟩ ⇝ e′ above
Γ[αk:=σ1] ⊢ops h[αk
:=σ1] : σ [αk:=σ1] | l | ϵ ⇝ h′[αk
:=σ1] Part 3
Γ[αk:=σ1]; ⟨⟨l : (m, h′[αk
:=σ1]) | w[αk:=σ1]⟩⟩ ⊢ e[αk
:=σ1] : σ | ⟨l | ϵ⟩ ⇝ e′[αk:=σ1] I.H.
Γ[αk:=σ1]; w[αk
:=σ1] ⊢ handleϵ h[αk:=σ1] e[αk
:=σ1] : σ | ⟨l | ϵ⟩ handle
⇝ handlewm h′[αk:=σ1] e′[αk
:=σ1]
Part 2 By induction on translation.
case v = x.Γ ⊢val x : σ ⇝ x given
x : σ ∈ Γ var
x : σ [αk:=σ1] ∈ Γ[α
k:=σ1] therefore
x[αk:=σ1] = x by substitution
Γ[αk:=σ1] ⊢val x : σ [αk
:=σ1] ⇝ x var
Γ[αk:=σ1] ⊢val x[αk
:=σ1] : σ [αk:=σ1] ⇝ x[αk
:=σ1] follows
case v = λϵ yσ2 . e.Γ ⊢val λϵ yσ2 . e : σ2→ σ3 ⇝ λϵ z : evv ϵ, y : ⌈σ2⌉ . e′ given
Γ, y :σ2; z ⊢ e : σ3 | ϵ ⇝ e′ abs
Γ[αk:=σ1], y :σ2[α
k:=σ1]; z[αk
:=σ1] ⊢ e[αk:=σ1] : σ3[α
k:=σ1] | ϵ ⇝ e′[αk
:=⌈σ1⌉] Part 1
Γ[αk:=σ1] ⊢val λϵ yσ2[α k
:=σ1]. e[αk:=σ1] : σ2[α
k:=σ1] → σ3[α
k:=σ1] abs
⇝ λϵ z : evv ϵ, y : ⌈σ2[αk:=σ1]⌉ . e′[αk
:=⌈σ1⌉]
⌈σ2[αk:=σ1]⌉ = ⌈σ2⌉[α
k:= ⌈σ1⌉] Lemma 15
Γ[αk:=σ1] ⊢val λϵ yσ2[α k
:=σ1]. e[αk:=σ1] : σ2[α
k:=σ1] → σ3[α
k:=σ1] abs
⇝ λϵ z : evv ϵ, y : ⌈σ2⌉[αk
:= ⌈σ1⌉]. e′[αk:=⌈σ1⌉]
case v = Λβk . v1.
43
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
Γ ⊢val Λβk . v1 : ∀βk . σ2 ⇝ Λβk . v ′1
given
Γ ⊢val v1 : σ2 ⇝ v ′1
tabs
Γ[αk:=σ1] ⊢val v1[α
k:=σ1] : σ2[α
k:=σ1] ⇝ v ′
1[αk
:=⌈σ1⌉] I.H.
Γ[αk:=σ1] ⊢val Λβk . v1[α
k:=σ1] : ∀βk . σ2[α
k:=σ1] ⇝ Λβk . v ′
1[αk
:=⌈σ1⌉] tabs
case v = perform op σ .Γ ⊢val perform op σ : σ2[α :=σ ] → σ3[α :=σ ] ⇝ perform op ⌈σ ⌉ given
op : ∀α . σ2→ σ3 ∈ Σ(l) perform
(perform op σ )[αk:=σ1] = perform op σ [αk
:=σ1] by substitution
Γ[αk:=σ1] ⊢val perform op σ [αk
:=σ1] perform
: σ2[α :=(σ [αk:=σ1])] → σ3[α :=(σ [αk
:=σ1])]
⇝ perform op ⌈σ [αk:=σ1]⌉
σ2[α :=(σ [αk:=σ1])]
= (σ2[αk:=σ1])[α :=(σ [αk
:=σ1])] α fresh to σ2
= (σ2[α :=σ ])[αk:=σ1] by substitution
σ3[α :=(σ [αk:=σ1])] = (σ3[α :=σ ])[αk
:=σ1] similarly
⌈σ [αk:=σ1]⌉ = ⌈σ ⌉[α
k:=⌈σ1⌉] Lemma 15
Γ[αk:=σ1] ⊢val perform op σ [αk
:=σ1] therefore
: (σ2[α :=σ ])[αk:=σ1] → (σ3[α :=σ ])[αk
:=σ1]
⇝ perform op ⌈σ ⌉[αk:=⌈σ1⌉]
case v = handlerϵ h.Γ ⊢val handlerϵ h : σ ⇝ handlerwm h′ given
Γ ⊢ops h : σ | l | ϵ ⇝ h′ handler
Γ[αk:=σ1] ⊢ops h[αk
:=σ1] : σ [αk:=σ1] | l | ϵ ⇝ h′[αk
:=⌈σ1⌉] Part 3
Γ[αk:=σ1] ⊢val handlerϵ h[αk
:=σ1] : σ [αk:=σ1] ⇝ handlerwm h′[αk
:=⌈σ1⌉] handler
Part 3 Follows directly from Part 2.
□
B.2.4 Translation Soundness.Proof. (Of Theorem 4) Apply Lemma 21 with Γ = ∅ and w = ⟨⟨⟩⟩. □
Lemma 21. (Evidence translation respects evidence typing with contexts)We use ⌈w⌉ϵ to mean that we extract fromw all evidence variables, who get their types by inspecting
ϵ . So we have:
1. If Γ ⊢val v : σ | ϵ ⇝ v ′ then ⌈Γ⌉ ⊩val v ′ : ⌈σ ⌉.2. If Γ;w ⊢ e : σ | ϵ ⇝ e′ then ⌈Γ⌉, ⌈w⌉ϵ ; w ⊩ e′ : ⌈σ ⌉ | ϵ .
3. If Γ ⊢ops h : σ | l | ϵ , then ⌈Γ⌉ ⊩ops ⌈h⌉ : ⌈σ ⌉ | l | ϵ .4. If Γ;w ⊢ E : σ1→ σ2 | ϵ ⇝ E′ then ⌈Γ⌉, ⌈w⌉ϵ ; w ⊢ E′ : ⌈σ1⌉ → ⌈σ2⌉.
Proof. (Of Lemma 21) Part 1 By induction on translation.
case v = x.Γ ⊢val x : σ | ϵ ⇝ x given
x :σ ∈ Γ var
x : ⌈σ ⌉ ∈ ⌈Γ⌉⌈Γ⌉ ⊩val x : ⌈σ ⌉ mvar
case v = λϵ xσ1 . e.
44
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
Γ ⊢val λϵ xσ1 . e : σ1→σ2 | ϵ ⇝ λϵ z evv ϵ , x σ1 · e′ given
Γ, x :σ1 ; z ⊢ e : σ2 | ϵ ⇝ e′ abs
⌈Γ⌉, x : ⌈σ1⌉, z : evv ϵ ; z ⊩ e′ : ⌈σ2⌉ | ϵ Part 2
⌈Γ⌉ ⊩ λϵ zevv ϵ , x : ⌈σ1⌉ . e′ : σ1⇒ϵ σ2 mabs
case v = Λα . v0.
Γ ⊢val Λα .v0 : ∀α . σ0 ⇝ Λα .v ′0
given
Γ ⊢val v0 : σ0 ⇝ v ′0
tabs
⌈Γ⌉ ⊩val v ′0
: ⌈σ0⌉ I.H.
⌈Γ⌉ ⊩val Λα . v ′0
: ∀α . ⌈σ0⌉ mtabs
case v = perform op.Γ ⊢val perform op : ∀µ α . σ1→ ⟨l | µ⟩ σ2 ⇝ perform op given
op : ∀α . σ1→ σ2 ∈ Σ(l) perform
op : ∀α . ⌈σ1⌉ → ⌈σ2⌉ ∈ ⌈Σ⌉(l)⌈Γ⌉ ⊩val perform op : ∀µ α . ⌈σ1⌉ ⇒ ⟨l | µ⟩ ⌈σ2⌉ mperform
case v = handlerϵ h.Γ ⊢val handlerϵ h : (()→⟨l | ϵ⟩σ ) →ϵ σ ⇝ handler h′ given
Γ ⊢ops h : σ | l | ϵ ⇝ h′ handler
⌈Γ⌉ ⊩ops h′ : ⌈σ ⌉ | l | ϵ Part 3
Γ ⊩val handlerϵ h′ : (()⇒⟨l | ϵ⟩ ⌈σ ⌉)⇒ϵ ⌈σ ⌉ mhandler
Part 2 By induction on translation.
case e = v.Γ;w ⊢ v : σ | ϵ ⇝ v ′ given
Γ ⊢val v : σ ⇝ v ′ var
⌈Γ⌉ ⊩val v ′ : ⌈σ ]⌉ Part 1
⌈Γ⌉, ⌈w⌉ϵ ⊩val v ′ : ⌈σ ]⌉ weakening
⌈Γ⌉, ⌈w⌉ϵ ; w ⊩ v ′ : ⌈σ ⌉ | ϵ mvar
case e = e1 e2.
Γ;w ⊢ e1 e2 : σ | ϵ ⇝ e′1w e′
2given
Γ;w ⊢ e1 : σ1→ ϵ σ | ϵ ⇝ e′1
app
Γ;w ⊢ e2 : σ1 | ϵ ⇝ e′1
app
⌈Γ⌉, ⌈w⌉ϵ ;w ⊢ e′1
: ⌈σ1⌉ ⇒ ϵ ⌈σ ⌉ | ϵ I.H.
⌈Γ⌉, ⌈w⌉ϵ ;w ⊢ e′2
: ⌈σ1⌉ | ϵ ⇝ e′2
I.H.
⌈Γ⌉, ⌈w⌉ϵ ;w ⊩ e′1w e′
2: ⌈σ ⌉ | ϵ mapp
case e = e1 [σ ].
Γ;w ⊢ e1 [σ ] : σ1[α :=σ ] | ϵ ⇝ e′1[⌈σ ⌉] given
Γ;w ⊢ e1 : ∀α . σ1 | ϵ ⇝ e′1
tapp
⌈Γ⌉, ⌈w⌉ϵ ;w ⊩ e′1
: ∀α . ⌈σ1⌉ | ϵ I.H.
⌈Γ⌉, ⌈w⌉ϵ ;w ⊩ e′1[⌈σ ⌉] : ⌈σ1⌉[α :=⌈σ ⌉] mtapp
⌈σ1⌉[α :=⌈σ ⌉] = ⌈σ1[α :=σ ]⌉ Lemma 15
case e = handleϵ h e.
45
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
Γ;w ⊢ handleϵ h e : σ | ϵ ⇝ handlewm h′ e′ given
Γ ⊢ops h : σ | l | ϵ ⇝ h′ handle
Γ; ⟨⟨l : (m, h) | w⟩⟩ ⊢ e : σ | ⟨l | ϵ⟩ ⇝ e′ above
⌈Γ⌉ ⊩ops h′ : ⌈σ ⌉ | l | ϵ ⇝ h′ Part 3
⌈Γ⌉ , ⌈⟨⟨(l : (m, h) | w)⟩⟩⌉ ⟨l |ϵ ⟩ ⊩ e′ : ⌈σ ⌉ | ⟨l | ϵ⟩ I.H.
⌈⟨⟨(l : (m, h) | w)⟩⟩⌉ ⟨l |ϵ ⟩ = ⌈⟨⟨w⟩⟩⌉ϵ by definition
⌈Γ⌉ , ⌈w⌉ϵ ;w ⊩ handlewm ⌈h⌉ ⌈e⌉ : ⌈σ ⌉ | ϵ mhandle
Part 3
Γ ⊢ops { op1→ f1, . . ., opn→ fn } : σ | l | ϵ ⇝ { opi → f ′i } given
opi : ∀α . σ1→ σ2 ∈ Σ(l) α ̸∩ ftv(ϵ σ ) ops
Γ ⊢val fi : ∀α . σ1→ ϵ (σ2→ ϵ σ ) → ϵ σ ⇝ f ′i above
opi : ∀α . ⌈σ1⌉ → ⌈σ2⌉ ∈ ⌈Σ⌉(l)⌈Γ⌉ ⊩val ⌈f ′i ⌉ : ∀α . ⌈σ1⌉ ⇒ ϵ (⌈σ2⌉ ⇒ ϵ ⌈σ ⌉)⇒ ϵ ⌈σ ⌉ Part 1
⌈Γ⌉ ⊩ops { op1→ f ′
1, . . ., opn→ f ′n } : ⌈σ ⌉ | l | ϵ mops
Part 4 By induction on translation.
case E = □. The goal follows trivially by mon-cempty.
case E = E0 e.Γ;w ⊢ec E0 e : σ1→ σ3 | ϵ ⇝ E′ w e′ given
Γ;w ⊢ e : σ2 | ϵ ⇝ e′ capp1
Γ;w ⊢ec E0 : σ1→ (σ2→ϵ σ3) | ϵ ⇝ E′ above
⌈Γ⌉, ⌈w⌉ϵ ;w ⊩ e′ : ⌈σ2⌉ | ϵ Part 2
⌈Γ⌉, ⌈w⌉ϵ ;w ⊩ec E′ : ⌈σ1⌉ → (⌈σ2⌉ ⇒ϵ ⌈σ3⌉) | ϵ I.H.
⌈Γ⌉, ⌈w⌉ϵ ;w ⊩ec E′ w e′ : ⌈σ1⌉ → ⌈σ3⌉ | ϵ mon-capp1
case E = v E0.
Γ;w ⊢ec v E0 : σ1→ σ3 | ϵ ⇝ v ′ w E′ given
Γ ⊢val v : σ2→ϵ σ3 ⇝ v ′ capp2
Γ;w ⊢ec E : σ1→ σ2 | ϵ ⇝ E′ above
⌈Γ⌉ ⊩val v ′ : ⌈σ2⌉ ⇒ϵ ⌈σ3⌉ Part 1
⌈Γ⌉, ⌈w⌉ϵ ;w ⊩ec E′ : ⌈σ1⌉ → ⌈σ2⌉ | ϵ I.H.
⌈Γ⌉, ⌈w⌉ϵ ;w ⊩ec v ′ w E′ : ⌈σ1⌉ → ⌈σ3⌉ | ϵ mon-capp2
case E = E0 [σ ].
Γ;w ⊢ec E0 [σ ] : σ1→ σ2 [α :=σ ] | ϵ ⇝ E′ [⌈σ ⌉] given
Γ;w ⊢ec E0 : σ1→ ∀α . σ2 | ϵ ⇝ E′ ctapp
⌈Γ⌉, ⌈w⌉ϵ ;w ⊩ec E′ : ⌈σ1⌉ → ∀α . ⌈σ2⌉ | ϵ I.H.
⌈Γ⌉, ⌈w⌉ϵ ;w ⊩ec E′ [⌈σ ⌉] : ⌈σ1⌉ → ⌈σ2⌉[α :=⌈σ ⌉] | ϵ mon-ctapp
⌈σ2⌉[α :=⌈σ ⌉] = ⌈σ2[α :=σ ]⌉ Lemma 15
case E = handleϵ h E0.
Γ;w ⊢ec handleϵ h E0 : σ1→ σ | ϵ ⇝ handlewm h′ E′ given
Γ ⊢ops h : σ | l | ϵ ⇝ h′ chandle
Γ; ⟨⟨l : (m, h′) | w⟩⟩ ⊢ec E : σ1→ σ | ⟨l | ϵ⟩ ⇝ E′ above
⌈Γ⌉ ⊩ops h′ : ⌈σ ⌉ | l | ϵ Part 3
⌈Γ⌉, ⌈⟨⟨l : (m, h′) | w⟩⟩⌉ ⟨l |ϵ ⟩ ; ⟨⟨(m, h′)l | w⟩⟩ ⊩ec E′ : ⌈σ1⌉ → ⌈σ ⌉ | ⟨l | ϵ⟩ I.H.
⌈Γ⌉, ⌈⟨⟨l : (m, h′) | w⟩⟩⌉ ⟨l |ϵ ⟩ ; w ⊩ec handlewm h′ E′ : ⌈σ1⌉ → ⌈σ ⌉ | ϵ mon-chandle
⌈⟨⟨(m, h′)l | w⟩⟩⌉ ⟨l |ϵ ⟩ = ⌈w⌉ϵ by definition
⌈Γ⌉, ⌈w⌉ϵ ; w ⊩ec handlewm h′ E′ : ⌈σ1⌉ → ⌈σ ⌉ | ϵ follows
46
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
□
B.3 System Fev
B.3.1 Evaluation Context Typing.Lemma 22. (Evaluation context typing)If Γ; w ⊩ec E : σ1→ σ2 | ϵ and Γ; ⌈E⌉,w ⊩ e : σ1 | ⟨⌈E⌉l | ϵ⟩, then Γ; w ⊩ E[e] : σ2 | ϵ .
Proof. (of Lemma 22) By induction on the evaluation context typing.
case E = □. The goal follows trivially.case E = E0 w e0.
Γ;w ⊩ec E0 w e0 : σ1→ σ2 | ϵ given
Γ;w ⊩ec E0 : σ1→ (σ3⇒ ϵ σ2) | ϵ mon-capp1
Γ;w ⊩ e0 : σ3 | ϵ above
Γ;w ⊩ E0[e] : σ3⇒ ϵ σ2 | ϵ I.H.
Γ;w ⊩ E0[e] w e0 : σ2 | ϵ mapp
case E = v w E0.
Γ;w ⊩ec v w E0 : σ1→ σ2 | ϵ given
Γ;w ⊩ v : σ3⇒ϵ σ2 | ϵ mon-capp2
Γ;w ⊩ec E0 : σ1→ σ3 | ϵ above
Γ;w ⊩ E0[e] : σ3 | ϵ I.H.
Γ;w ⊩ v w E0[e] : σ2 | ϵ mapp
case E = E0 [σ ].
Γ;w ⊩ec E0 [σ ] : σ1→ σ2 | ϵ given
Γ;w ⊩ec E0 : σ1→ ∀α . σ3 | ϵ mon-ctapp
σ3[α :=σ ] = σ1→ σ2 above
Γ;w ⊩ E0[e] : ∀α . σ3 | ϵ I.H.
Γ;w ⊩ E0[e] [σ ] : σ3[α :=σ ] | ϵ mtapp
case E = handlew h E0.
Γ;w ⊩ec handlew h E0 : σ1→ σ2 | ϵ given
Γ; ⟨⟨l : (m, h) | w⟩⟩ ⊩ec E0 : σ1→ σ2 | ⟨l | ϵ⟩ mon-chandle
Γ ⊩ops h : σ | l | ϵ above
Γ; ⟨⟨l : (m, h) | w⟩⟩ ⊩ec E0[e] : σ2 | ⟨l | ϵ⟩ I.H.
Γ;w ⊩ handlew h E0[e] : σ2 | ϵ mhandle
□
Proof. (Of Lemma 6) Induction on E.case E = □. Let σ1 = σ and the goal holds trivially.
case E = E0 w e0.
∅;w ⊩ E0[e] w e0 : σ | ϵ given
∅;w ⊩ E0[e] : σ2⇒ϵ σ | ϵ mapp
∅; ⟨⟨⌈E0⌉ | w⟩⟩ ⊩ e : σ1 | ⟨⌈E0⌉l | ϵ⟩ I.H.
⌈E⌉ = ⌈E0 w e0⌉ = ⌈E0⌉ by definition
⌈E⌉l = ⌈E0 w e0⌉l = ⌈E0⌉
lby definition
case E = v w E0.
47
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
∅;w ⊩ v w E0[e] : σ | ϵ given
∅;w ⊩ E0[e] : σ2 | ϵ mapp
∅; ⟨⟨⌈E0⌉ | w⟩⟩ ⊩ e : σ1 | ⟨⌈E0⌉l | ϵ⟩ I.H.
⌈E⌉ = ⌈v w E0⌉ = ⌈E0⌉ by definition
⌈E⌉l = ⌈v w E0⌉l = ⌈E0⌉
lby definition
case E = E0 [σ ].
∅;w ⊩ E0[e] [σ ] : σ | ϵ given
∅;w ⊩ E0[e] : ∀α . σ2 | ϵ mtapp
∅; ⟨⟨⌈E0⌉ | w⟩⟩ ⊩ e : σ1 | ⟨⌈E0⌉l | ϵ⟩ I.H.
⌈E⌉ = ⌈E0 [σ ]⌉ = ⌈E0⌉ by definition
⌈E⌉l = ⌈E0 [σ ]⌉l = ⌈E0⌉
lby definition
case E = handlem h E0.
∅;w ⊩ handlem h E0[e] : σ | ϵ given
∅; ⟨⟨l : (m, h) | w⟩⟩ ⊩ E0[e] : σ | ⟨l | ϵ⟩ mhandle
∅⊩ops h : σ | l | ϵ above
∅; ⟨⟨⌈E0⌉ | l : (m, h) | w⟩⟩ ⊩ e : σ1 | ⟨⌈E0⌉l | l | ϵ⟩ I.H.
⟨⟨⌈E0⌉ | l : (m, h)⟩⟩ = ⟨⟨⌈handlem h · E0⌉⟩⟩ by definition
⟨⌈E⌉l ⟩ = ⌈handlem h E0⌉l = ⟨⌈E0⌉ | l⟩ by definition
□
Proof. (Of Lemma 7)
∅; ⟨⟨⟩⟩ ⊢ E[perform op σ v] : σ | ⟨⟩ given
∅; ⌈E⌉ ⊢ perform op σ v : σ1 | ⌈E⌉l Lemma 6
∅; ⌈E⌉ ⊢ perform op σ : σ2→⌈E⌉l σ1 | ⌈E⌉l app
∅ ⊢val perform op σ : σ2→ ⌈E⌉l σ1 val
l ∈ ⌈E⌉l op
E = E1 · handlewm h · E2 By definition of ⌈E⌉l
op→ f ∈ h above
op ̸∈ bop(E2) Let handleϵ h be the innermost one
□
B.3.2 Correspondence.Proof. (Of Theorem 5)
∅; ⟨⟨⟩⟩ ⊩ev E[perform op σ w v] : σ | ⟨⟩ given
∅; ⌈E⌉ ⊩ev perform op σ w v : σ1 | ⌈E⌉l Lemma 6
w = ⌈E⌉ mapp
E = E1 · handlewm h · E2 Lemma 7
op ̸∈ bop(E2), (op→ f ) ∈ h above
l ̸∈ ⌈E2⌉l
or otherwise op ∈ bop(E2)
⌈E1. handlewm h · E2⌉ = ⟨⟨⌈E2⌉ | ⟨⟨l : (m, h) | ⌈E1⌉⟩⟩⟩⟩ by definition
⟨⟨⌈E2⌉ | ⟨⟨l : (m, h) | ⌈E1⌉⟩⟩⟩⟩.l = ⟨⟨l : (m, h) | ⌈E1⌉⟩⟩.l Follows
w.l = ⌈E⌉ .l = ⟨⟨l : (m, h) | ⌈E1⌉⟩⟩.l = (m, h)□
B.3.3 Substitution.
48
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
Lemma 23. (Substitution)1. If Γ1, x : σ , Γ2 ⊩val v1 : σ1 , and Γ1 , Γ2 ⊩val v : σ , then Γ1, Γ2 ⊩val v1 [x:= v] : σ1 .
2. If Γ1, x : σ , Γ2 ; w ⊩ e1 : σ1 | ϵ and Γ1 , Γ2 ⊩val v : σ ,
then Γ1, Γ2 ; w [x := v] ⊩ e1 [x:= v] : σ1 | ϵ .
3. If Γ1, x :σ , Γ2 ⊩ops { op1→ f1, . . ., opn→ fn } : σ1 | l | ϵ and Γ1, Γ2 ⊩val v : σ ,
then Γ1, Γ2⊩ops ({ op1→ f1, . . ., opn→ fn })[x:=v] : σ1 | l | ϵ .
4. If Γ1, x :σ , Γ2 ; w ⊩ec E : σ1→ σ2 | ϵ and Γ1 , Γ2 ⊩val v : σ ,
then Γ1, Γ2 ; w[x:=v] ⊩ec E [x:=v] : σ1→ σ2 | ϵ .
Proof. (Of Lemma 23) Apply Lemma 34, ignoring all translations. □
Lemma 24. (Type Variable Substitution)1. If Γ ⊩val v : σ and⊢wf σ1 : k,then Γ[αk
:=σ1] ⊩val v[αk:=σ1] : σ [αk
:=σ1].
2. If Γ;w ⊩ e : σ | ϵ and⊩wf σ1 : k,then Γ[αk
:=σ1];w[αk:=σ1] ⊩ e[αk
:=σ1] : σ [αk:=σ1] | ϵ .
3. If Γ ⊩ops h : σ | l | ϵ and⊢wf σ1 : k,then Γ[αk
:=σ1] ⊩ops h[αk:=σ1] : σ [αk
:=σ1] | l | ϵ .4. If Γ;w ⊩ E : σ1→ σ2 | ϵ and⊢wf σ1 : k,then Γ[αk
:=σ1];w[αk:=σ1] ⊩ E[αk
:=σ1] : σ1[αk:=σ1] → σ2[α
k:=σ1] .
Proof. (Of Lemma 24) Apply 35, ignoring all translations. □.
Lemma 25. (Values can have any effect)1. If Γ ; w1 ⊩ v : σ | ϵ1 , then Γ ; w2 ⊩ v : σ | ϵ2.
2. If Γ ; w1 ⊢ v : σ | ϵ1 ⇝ v ′, then Γ ; w2 ⊢ v : σ | ϵ2 ⇝ v ′.
Proof. (Of Lemma 25)Part 1 By mval, we have Γ ⊩val v : σ . By mval, we have Γ ; w2 ⊩ v : σ | ϵ2 .
Part 2 By val, we have Γ ⊢val v : σ ⇝ v ′. By val, we have Γ ; w2 ⊢ v : σ | ϵ2 ⇝ v ′ . □
B.3.4 Preservation.Proof. (Of Theorem 7)
Let e1 = E[e′1], and e2 = E[e′
2].
∅; ⟨⟨⟩⟩ ⊩ E[e′1] : σ | ⟨⟩ given
∅; ⌈E⌉ ⊩ e′1
: σ1 | ⌈E⌉l Lemma 6
∅; ⟨⟨⟩⟩ ⊩ E : σ1→ σ | ⟨⟩ above
e′1−→ e′
2given
∅; ⌈E⌉ ⊩ e′2
: σ1 | ⌈E⌉l Lemma 26
∅; ⟨⟨⟩⟩ ⊩ E[e′2] : σ | ⟨⟩ Lemma 22
□
Lemma 26. (Small step preservation of evidence typing)If ∅; w ⊩ e1 : σ | ϵ and e1 −→ e2, then ∅; w ⊩ e2 : σ | ϵ .
Proof. (Of Lemma 26) By induction on reduction.
case (λϵ z : evv ϵ, x :σ1. e) w v −→ e[z:=w, x:=v].
49
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
∅;w ⊩ (λϵ z : evv ϵ, x :σ1. e) w v : σ2 | ϵ given
∅;w ⊩ λϵ z : evv ϵ, x :σ1. e : σ1⇒ ϵ σ2 | ϵ mapp
∅;w ⊩ v : σ1 | ϵ above
z : evv ϵ, x :σ1; z ⊩ e : σ2 | ϵ mabs
x :σ1;w ⊩ e[z:=w] : σ2 | ϵ Lemma 23
∅;w ⊩ e[z:=w, x:=v] : σ2 | ϵ Lemma 23
case (Λα . v) [σ ] −→ v[α :=σ ].
∅;w ⊩ (Λα . v) [σ ] : σ1 [α :=σ ] | ϵ given
∅;w ⊩ Λα . v : ∀α . σ1 | ϵ mtapp
∅ ⊩val Λα . v : ∀α · σ1 mval
∅ ⊩val v : σ1 mtabs
∅;w ⊩val v : σ1 | ϵ mval
∅;w ⊩val v[α :=σ ] : σ1[α :=σ ] | ϵ Lemma 24
case (handlerϵ h) w v −→ handlewm h (v ⟨⟨l : (m, h) | w⟩⟩ ()) with a unique m.
∅;w ⊩ (handlerϵ h) w v : σ | ϵ given
∅;w ⊩ handlerϵ h : (()⇒ ⟨l | ϵ⟩ σ )⇒ ϵ σ | ϵ mapp
∅;w ⊩ v : ()⇒ ⟨l | ϵ⟩ σ | ϵ above
∅ ⊩val handlerϵ h : (()⇒ ⟨l | ϵ⟩ σ )⇒ ϵ σ mval
∅ ⊩ops h : σ | l | ϵ mhandler
∅; ⟨⟨l : (m, h) | w⟩⟩ ⊩ v : ()⇒ ⟨l | ϵ⟩ σ | ⟨l | ϵ⟩ Lemma 25
∅; ⟨⟨l : (m, h) | w⟩⟩ ⊩ v ⟨⟨l : (m, h) | w⟩⟩ () : σ | ⟨l | ϵ⟩ mapp
∅;w ⊩ handlewm h (v ⟨⟨l : (m, h) | w⟩⟩ ()) : σ | ⟨ϵ⟩ mhandle
case handlewm h · v −→ v.∅;w ⊩ handlewm h · v : σ | ϵ given
∅; ⟨⟨l : (m, h) | w⟩⟩ ⊩ v : σ | ⟨l | ϵ⟩ mhandle
∅;w ⊩ v : σ | ⟨ϵ⟩ Lemma 25
case handlewm h · E · perform op σ w ′ v −→ f σ w v w k.op ̸∈ bop(E) and op→ f ∈ h given
op : ∀α . σ1→ σ2 ∈ Σ(l) given
k = guardw (handlewm h · E) σ2[α :=σ ] given
∅; w ⊩ handlewm h · E · perform op σ w ′ v : σ | ϵ given
∅⊩ops h : σ | l | ϵ mhandle
∅⊩val f : ∀α . σ1⇒ ϵ (σ2⇒ ϵ σ )⇒ ϵ σ mops
∅; w ⊩ f : ∀α . σ1⇒ ϵ (σ2⇒ ϵ σ )⇒ ϵ σ | ϵ mval
∅; w ⊩ f σ : σ1[α :=σ ]⇒ ϵ (σ2[α :=σ ]⇒ ϵ σ )⇒ ϵ σ | ϵ mtapp
∅; ⟨⟨⌈E⌉ | l : (m, h) | w⟩⟩ ⊩ perform op σ w ′ v : σ2[α :=σ ] | ⟨⌈E⌉l | l | ϵ⟩ Lemma 6
∅; w ⊩ec handlewm · E : σ2[α :=σ ] → σ | ϵ above
∅; ⟨⟨⌈E⌉ | l : (m, h) | w⟩⟩ ⊩ v : σ1[α := σ ] | ⟨⌈E⌉l | l | ϵ⟩ mapp and mtapp
∅; w ⊩ v : σ1[α := σ ] | ϵ Lemma 25
∅; w ⊩ f σ w v : (σ2[α :=σ ] → ϵ σ )⇒ ϵ σ | ϵ mapp
∅ ⊩val guardw (handlewm h · E) σ2[α :=σ ] : σ2[α :=σ ]⇒ ϵ σ mguard
∅;w ⊩ guardw (handlewm h · E) σ2[α :=σ ] : σ2[α :=σ ]⇒ ϵ σ | ϵ mval
∅; w ⊩ f σ w v w k : σ | ϵ mapp
case (guardw1 E σ1) w v −→ E[v].
50
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
∅;w ⊩ guardw E σ1 w v : σ | ϵ given
∅;w ⊩ guardw E σ1 : σ1⇒ϵ σ | ϵ mapp
∅;w ⊩ v : σ1 | ϵ above
∅ ⊩val guardw E σ1 : σ1⇒ϵ σ mval
∅;w ⊩ec E : σ1→ σ | ϵ mguard
∅; ⟨⟨⌈E⌉ | w⟩⟩ ⊩ v : σ1 | ⟨⌈E⌉l | ϵ⟩ Lemma 25
∅;w ⊩ec E : σ1→ σ | ϵ mguard
∅;w ⊩ E[v] : σ | ϵ Lemma 22
□
B.3.5 Translation Coherence. We define the equivalence relation inductively as follows.
e[z:=w] � E[x]
λϵ z, x :σ . e � guardw E σ[eq-guard]
E[x] � e[z:=w]
guardw E σ � λϵ z, x :σ . e[eq-guard-symm]
m1 � m2
[eq-marker]
x � x[eq-var]
e1 � e2
λϵ z : evv ϵ, x : σ · e1 � λϵ z : evv ϵ, x : σ . e2
[eq-abs]
w1 � w2 E1 � E2
guardw1 E1 σ � guardw2 E2 σ[eq-guard]
e1 � e3 w1 � w2 e2 � e4
e1 w1 e3 � e2 w2 e4
[eq-app]
v1 � v2
Λα . v1 � Λα . v2
[eq-tabs]
e1 � e2
e1[σ ] � e2[σ ][eq-tapp]
perform op � perform op[eq-perform]
h1 � h2
handlerϵ h1 � handlerϵ h2
[eq-handler]
51
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
m1 � m2 w1 � w2 e1 � e2 h1 � h2
handlew1
m1h1 e1 � handlew2
m2h2 e2
[eq-handle]
Lemma 27. (Translation is deterministic)1. If Γ;w ⊢ e : σ | ϵ ⇝ e1, and Γ;w ⊢ e :σ | ϵ ⇝ e2, then e1 and e2 are equivalent up to eq-marker.
By definition, we also have e1 � e2.
2. If Γ ⊢val v : σ ⇝ v1, and Γ ⊢val v :σ ⇝ v2, then v1 and v2 are equivalent up to eq-marker. By
definition, we also have v1 � v2.
3. If Γ ⊢ops h : σ | ϵ ⇝ h1 , and Γ ⊢ops h : σ | ϵ ⇝ h2, then h1 and h2 are equivalent up to eq-marker.
By definition, we also have h1 � h2.
4. If Γ;w ⊢ec E : σ1→ σ2 | ϵ ⇝ E1, and Γ;w ⊢ec E : σ1→ σ2 | ϵ ⇝ E2, then E1 and E2 are equiv-
alent up to eq-marker. By definition, we also have E1 � E2.
Proof. (Of Lemma 27) By a straightforward induction on the translation. Note the only difference
is introduced in handle and chandle, where we may have chosen different m’s. □
Lemma 28. (Evaluation context equivalence)If E1 � E2, and e1 � e2, then E1[e1] � E2[e2].
Proof. (Of Lemma 28) By a straightforward induction on the context equivalence. □
Lemma 29. (Equivalence substitution)1. If e1 � e2, and v1 � v2, then e1[x:=v1] � e2[x:=v2].
2. If e1 � e2, then e1[α :=σ ] � e2[α :=σ ].
Proof. (Of Lemma 29) By a straightforward induction on the equivalence relation. □
Proof. (Of Lemma 8) By induction on the reduction.
case e1 = (λϵ z : evv ϵ, x : σ . e′
1) w1 v1 and e1 −→ e′
1[z:=w1, x:=v1].
By case analysis on the equivalence relation.
subcase e2 = (λϵ z : evv ϵ, x : σ . e′
2) w2 v2 with e′
1� e′
2, w1 � w2 and v1 � v2.
(λϵ z : evv ϵ, x : σ . e′2) w2 v2 −→ e′
2[z:=w2, x:=v2] (app)
e′1[z:=w1, x:=v1] � e′
2[z:=w2, x:=v2] Lemma 29
subcase e2 = (guardw E σ ) w2 v2 with e′1[z:=w] � E[x], w1 � w2 and v1 � v2. We discuss
whether w2 is equivalent to w.• w2 = w.
guardw2 E σ w2 v2 −→ E[v2] (guard)e′
1[z:=w2] � E[x] given
e′1[z:=w1] � E[x] w1 � w2
(e′1[z:=w1])[x:=v1] � (E[x])[x:=v2] Lemma 29
• w2 , w. Then e2 get stuck as no rule applies.
case e1 = (Λα . e′1) [σ ] and e1 −→ e′1[α :=σ ].
e2 = (Λα . e′2) [σ ] by equivalence
e′1� e′
2above
e2 −→ e′2[α :=σ ] (tapp)
e′1[α :=σ ] � e′
2[α :=σ ] Lemma 29
case e1 = (handlerϵ h1) w1 v1 and e1 −→ handlew1
m h1 (v1 ⟨⟨l : (m, h) | w1⟩⟩ ()).
52
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
e2 = (handlerϵ h2) w2 v2 by equivalence
v1 � v2 above
w1 � w2 above
h1 � h2 above
e2 −→ handlew2
m hh (v2 ⟨⟨l : (m, h) | w2⟩⟩ ()) (handler)handlew1
m h1 (v1 ⟨⟨l : (m, h) | w1⟩⟩ ()) � handlew2
m h2 (v2 ⟨⟨l : (m, h) | w2⟩⟩ ()) congruence
case e1 = handlew1
m h1 · v1 and e1 −→ v1.
e2 = handlew2
m h2 · v2 by equivalence
v1 � v2 above
w1 � w2 above
h1 � h2 above
e2 −→ v2 (return)
case e1 = handlew1
m h1 · E1 · performϵ ′ op [σ ] w ′ v1 and e1 −→ f1 [σ ] w v1 w k1,
where k1 = guardw1 (handlew1
m h · E1) σ2[α :=σ ] .
e2 = handlew2
m h · E2 · performϵ ′ op [σ ] w ′ v2 by equivalence
v1 � v2 above
w1 � w2 above
E1 � E2 above
h1 � h2 above
f1 � f2 therefore
e2 −→ f2 [σ ] w2 v2 w2 k2 (perform)k2 = guardw2 (handlew2
m h · E2) σ2[α :=σ ] above
k1 � k2 congruence
f1 [σ ] w1 v1 w1 k1 � f2 [σ ] w2 v2 w2 k2 congruence
case e1 = (guardw1 E1 σ ) w1 v1 and e1 −→ E1[v1].
By case analysis on the equivalence relation.
subcase
e2 = (guardw2 E2 σ ) w3 v2 by equivalence
E1 � E2 above
v1 � v2 above
w1 � w2 above
w1 � w2 above
If w2 = w3, then e2 gets stuck as no rule applies.
If w2 = w3, then
e2 −→ E2[v2] (guard)E1[v1] � E2[v2] Lemma 28
subcase
e2 = (λz, x . e2) w2 v2 by equivalence
w1 � w2 above
v1 � v2 above
E1[x] � e2[z:=w1] above
E1[x] � e2[z:=w2] w1 � w2
e2 −→ e2[z:=w2, x:=v2] (app)(E1[x])[x:=v1] � (e2[z:=w2])[x:=v2] Lemma 29
53
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
□
Lemma 30. (Small step evidence translation is coherent)If∅ ; w ⊢ e1 : σ | ϵ ⇝ e′
1and e1 −→ e2, and∅; w ⊢ e2 : σ | ϵ ⇝ e′
2, then exists a e′′
2, such that
e′1−→ e′′
2and e′′
2� e′
2.
Proof. (Of Lemma 30) By case analysis on the induction.
case (λϵx :σ1. e) v −→ e[x:=v] .∅; w ⊢ (λϵx :σ1. e) v : σ | ϵ ⇝ (λϵ z : evv ϵ, x : ⌈σ1⌉ . e′) w v ′ given
(λϵ z : evv ϵ, x : ⌈σ1⌉ . e′) w v ′ −→ e′[z:=w][x : v] (app)∅; w ⊢ λϵ x : σ1. e : σ1→ϵ σ | ϵ ⇝ (λϵ z : evv ϵ, x : ⌈σ1⌉ · e′) app
∅; w ⊢ v : σ1 | ϵ ⇝ v ′ above
∅ ⊢val λϵ x : σ1. e : σ1→ϵ σ ⇝ (λϵ z : evv ϵ, x : ⌈σ1⌉ · e′) val
x :σ1; z ⊢ e : σ | ϵ ⇝ e′ abs
x :σ1; z[z:=w] ⊢ e : σ | ϵ ⇝ e′[z:=w] Lemma 19
x :σ1; w ⊢ e : σ | ϵ ⇝ e′[z:=w] by substitution
∅⊢val v : σ1 ⇝ v ′ val
∅; w ⊢ e[x:=v] : σ | ϵ ⇝ e′[z:=w][x:=v ′] Lemma 18
case (Λα . v) [σ ] −→ v[α :=σ ].
∅;w ⊢ (Λα . v) [σ ] : σ1[α :=σ ] | ϵ ⇝ (Λα . v ′) [⌈σ ⌉] given
∅;w ⊢ Λα . v : ∀α . σ1 | ϵ ⇝ Λα . v ′ tapp
(Λα . v ′) [⌈σ ⌉] −→ v ′[α :=⌈σ ⌉] (tapp)∅;w ⊢ v : σ1 | ϵ ⇝ v ′ tabs
∅;w ⊢ v[α :=σ ] ⇝ v ′[α :=⌈σ ⌉] Lemma 20
case (handlerϵ h) v −→ handleϵ h (v ()).∅; w ⊢ (handlerϵ h) v : σ | ϵ ⇝ (handlerϵ h′) w v ′ given
∅; w ⊢ v : σ | ϵ ⇝ v ′ app
∅; ⟨⟨(l :m, h) | w⟩⟩ ⊢ v : σ | ⟨l | ϵ⟩ ⇝ v ′ Lemma 25
∅;w ⊢ handleϵ h (v ()) : σ | ϵ ⇝ (handlewm h′ (v ′ ⟨⟨l : (m, h) | w⟩⟩ () ) ) given
(handlerϵ h′) w v −→ handlewm h′ (v ′ ⟨⟨l : (m, h) | w⟩⟩ ()) (handler)case handleϵ h · v −→ v
∅;w ⊢ handleϵ h · v : σ | ϵ ⇝ handlewm w v ′ given
∅; ⟨⟨l : (m, h) | w⟩⟩ ⊢ v : σ | ⟨l | ϵ⟩ v ′ handle
∅;w ⊢ v : σ | ϵ ⇝ v ′ Lemma 25
handlewm w v ′ −→ v ′ (return)case handleϵ h · E · perform op σ v −→ f σ v k .
54
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
op :∀α . σ1→ σ2 ∈ Σ(l) given
k = λϵ x : σ2[α :=σ ]. handleϵ h · E · x given
∅; w ⊢ handleϵ h · E · perform op σ v : σ | ϵ given
⇝ handlewm1
h1 · E1 · perform op ⌈σ ⌉ w ′ v∅; w ⊢ec handleϵ h · E : σ2→ σ | ϵ ⇝ handlewm1
h1 · E1 Lemma 17
x :σ2[α :=σ ]; w ⊢ec handleϵ h · E : σ2[α :=σ ] → σ | ϵ ⇝ handlewm1
h1 · E1 Weakening
x :σ2[α :=σ ]; w ⊢ x : σ2[α :=σ ] ⇝ x | ϵ var and val
x :σ2[α :=σ ]; w ⊢ec handleϵ h · E · x : σ2[α :=σ ] → σ | ϵ Lemma 16
⇝ handlewm1
h1 · E1 · x∅ ; w ⊢ λϵ x : σ2[α :=σ ]. handleϵ h · E · x : σ2[α :=σ ] → σ | ϵ given
⇝ λϵ z : evv ϵ, x : ⌈σ2[α :=σ ]⌉ . handlezm2
h2 · E2 · xk1 = λϵ z : evv ϵ, x : ⌈σ2[α :=σ ]⌉ . handlezm2
h2 · E2 · x let
∅; w ⊢ f σ v k : σ | ϵ ⇝ f ′ ⌈σ ⌉ w v ′w k1 app
k2 = guardw (handlewm1
h1 · E1) σ2[α :=σ ] let
handlewm1
h1 · E1 · perform op ⌈σ ⌉ w ′ v −→ f ′ ⌈σ ⌉ w v ′ w k2 (perform)∅ ⊢val λϵ x : σ2[α :=σ ]. handleϵ h · E · x : σ2[α :=σ ] → σ val
⇝ λϵ z : evv ϵ, x : ⌈σ2[α :=σ ]⌉ . handlezm2
h2 · E2 · xx : σ2[α :=σ ] ; z ⊢ handleϵ h · E · x : σ | ϵ ⇝ handlezm2
h2 · E2 · x abs
x : σ2[α :=σ ] ; z[z:=w] ⊢ handleϵ h · E · x : σ | ϵ Lemma 19
⇝ (handlezm2
h2 · E2 · x) [z:=w](handlezm2
h2 · E2 · x)[z:=w] � handlewm1
h1 · E1 · x Lemma 27
λϵ z : evv ϵ, x : ⌈σ2[α :=σ ]⌉ . handlezm2
h2 · E2 · x eq-guard
� guardw (handlewm1
h1 · E1) σ2[α :=σ ]k1 � k2 namely
f ′ ⌈σ ⌉ w v ′ w k1 � f ′ ⌈σ ⌉ w v ′w k2 congruence
□
Proof. (Of Theorem 8)
e1 7−→ e2 given
e1 = E1[e3] step
e2 = E1[e4] above
e3 −→ e4 above
∅; ⟨⟩ ⊢ E1[e3] : σ | ⟨⟩ ⇝ e′1
given
e′1= E′
1[e′
3] Lemma 17
∅; ⟨⟩ ⊢ E1 : σ1→ σ | ⟨⟩ ⇝ E′1
above
∅; ⌈E′1⌉ ⊢ e3 : σ1 | ⌈E′1⌉
l ⇝ e′3
above
∅; ⟨⟩ ⊢ E1[e4] : σ | ⟨⟩ ⇝ e′2
given
e′2= E′′
1[e′
4] Lemma 17
∅; ⟨⟩ ⊢ E1 : σ1→ σ | ⟨⟩ ⇝ E′′1
above
∅; ⌈E′1⌉ ⊢ e4 : σ1 | ⌈E′1⌉
l ⇝ e′4
above
e3 � e4 Lemma 30
E′1� E′′
1Lemma 27
E′1[e′
3] � E′′
1[e′
4] Lemma 28
□
55
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
B.3.6 Uniqueness of handlers. Handle-safe expressions have the following induction principle: (1)
(base case) If e contains no handlewm terms, then e has the property; (2) (induction step) If e1 has the
property, and e1 7−→ e2 , then e2 has the property.
Lemma 31. (Handle-evidence in handle-safe Fev expressions is closed)If a handle-safe expression contains handlewm h e, then w has no free variables.
Proof. (Of Lemma 31) Base case: Since there is no handlewm h e, the lemma holds trivially.
Induction step: We want to prove that if e1 has the property, and e1 7−→ e2,then e2 has the
property. We do case analysis of the operational semantics.
case E · (λϵ z : evv ϵ, x :σ . e) w v 7−→ E · e[z:=w, x:=v].We know that in e, we have w1 in handlew0
m h e0 is closed, therefore
(handlew0
m h e0)[z:=w, x:=v] = handlew0
m h[z:=w, x:=v] e0[z:=w, x:=v] and w0 is still closed. And
other handle evidences in E are already closed.
case E · (Λαk . v) [σ ] 7−→ E · v[α :=σ ].We know that in e, we have w1 in handlew0
m h e0 is closed, therefore
(handlew0
m h e0)[α :=σ ] = handlew0
m h[α :=σ ] e0[α :=σ ] and w0 is still closed. And other handle evi-
dences in E are already closed.
case E · (handlerϵ h) w v 7−→ E. handlewm1
h (v ⟨⟨l : (m1, h) | w⟩⟩ ()) with m1 unique. We know that
w is closed. And other handle evidences in E are already closed.
case E · handlewm h · v 7−→ E · v.We already know handle evidences in E and v are closed.
case E1 · handlewm h · E2 · perform op σ w ′ v 7−→ E1 · f [σ ] w v w k,where k = guardw (handlewm h · E2) (σ2[α :=σ ]) and (op→ f ) ∈ h.
We know that w is closed. And other handle evidences in E1,E2,f ,v are already closed.
case E1 · (guardw E σ ) w v 7−→ E1 · E[v].We already know handle evidences in E, E1 and v are closed. □
Definition 2. (m-mapping)We say an expression e is m-mapping, if every m in e can uniquely determine its w and h. Namely,
if e contains handlew1
m h1 e1 and handlew2
m h2 e2, then w1 = w2 and h1 = h2.
Lemma 32. (Handle-free Fev expression is m-mapping)Any handle-free Fev expression e is m-mapping.
Proof.Base case: Since there is no handlewm, there is no m. So e is m-mapping trivially.
Induction step: We want to prove that if e1 is m-mapping, and e1 7−→ e2,then e2 is m-mapping.
By case analysis on e1 7−→ e2.
case E · (λϵ z : evv ϵ, x :σ · e) w v 7−→ E · e[z:=w, x:=v].Due to Lemma 31, we know all handle-evidences are closed. Therefore, the substitution does not
change those handle-evidences, and for all original pair of handlew1
m h1 e1 and handlew2
m h2 e2 for
each m, we know w1 = w2 still holds true.
Note v may be duplicated in e, which can introduce new pairs. Consider
(λx . (x, x)) (λz. handlezm e) −→ ((λz. handlezm e), (λz. handlezm e)). Here the argument is dupli-
cated, and now we have a new pair (λz. handlezm e) and (λz. handlezm e), where m maps to two z’s.Unfortunately, those z’s are actually different, as under α-renaming, the expression is equivalent to
((λz1. handlez1
m e), (λz2. handlez2
m e)). And we have z1 , z2!
56
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
Luckily, this situation cannot happen for handle-safe expressions. As due to Lemma 31, handlewmhas no free variables in w. Therefore, for one handle handlewm, even if it is duplicated, for the new
pair handlewm and handlewm, we still have w = w.case E · (Λαk . v) [σ ] 7−→ E · v[α :=σ ].Due to Lemma 31, we know all handle-evidences are closed. Therefore, the substitution does not
change those handle-evidences, and for all original pair of handlew1
m h1 e1 and handlew2
m h2 e2 for
each m, we know w1 = w2 still holds true.
case E · (handlerϵ h) w v 7−→ E. handlewm1
h (v ⟨⟨l : (m1, h) | w⟩⟩ ()) with m1 unique.
Every pair in E, h and v is a pair in E · (handlerϵ h) w v. So it is still m-mapping.
Given m1 unique, we know there is no other handlew2
m1h2 e2.
So E · handlewm1
h (v ⟨⟨l : (m1, h) | w⟩⟩ ()) is m-mapping.
case E · handlewm h · v 7−→ E · v.Every pair in E · v is a pair in E · handlewm h · v.
So we know it is m-mapping.
case E · handlewm h · E · perform op σ w ′ v 7−→ E · f [σ ] w v w k,where k = guardw (handlewm h · E) (σ2[α :=σ ]) and (op→ f ) ∈ h.
Every pair in E · f [σ ] w v w k is a pair in E · hanndlewm h · E · perform op σ w ′ v.So we know it is m-mapping.
case E1 · (guardw E σ ) w v 7−→ E1 · E[v].Every pair in E1 · E[v] is a pair in E1 · (guardw E σ ) w v.
So we know it is m-mapping. □
Proof. (Of Theorem 6) We prove it by contradiction.
m1 = m2 suppose
w1 = w2 Lemma 32
Γ ; w ⊩ E1 · handlew1
m1h · E2 · handle
w2
m2h · e0 : σ | ϵ given
Γ ; w ⊩ E1 · handlew1
m1h · E2 · handle
w1
m2h · e0 : σ | ϵ w1 = w2
Γ ; ⟨⟨ ⌈E1⌉ | w ⟩⟩ ⊩ handlew1
m1h · E2 · handle
w1
m2h · e0 : σ1 | ⟨⌈E1⌉
l | ϵ⟩ Lemma 6
w1 = ⟨⟨ ⌈E1⌉ | w ⟩⟩ mhandle
Γ ; ⟨⟨ ⌈E1 · handlew1
m1h · E2 ⌉ | w ⟩⟩ ⊩ handlew1
m2h · e0 : σ2 | ⟨⌈E1 · handle
w1
m1h · E2 ⌉
l | ϵ⟩ Lemma 6
w1 = ⟨⟨ ⌈E1 · handlew1
m1h · E2 ⌉ | w ⟩⟩ mhandle
⟨⟨ ⌈E1⌉ | w ⟩⟩ = ⟨⟨ ⌈E1 · handlew1
m1h · E2 ⌉ | w ⟩⟩ follows
contradiction
□
B.4 Monadic TranslationDuring the proof, we also use the inverse monadic bind, defined as
g ◁ pure x = g xg ◁ (yield m f cont) = yield m f (g • cont)
B.4.1 Multi-Prompt Delimited Continuations.Proof. (of Theorem 9) By induction over the evaluation rules. In particular,
handlewm h · E · performl op w ′ v −→ f w v w kwhere op→ f ∈ h (1), k = guardw (handlewm h · E)(2), and op ̸∈ bop(E) (3).
In that case, by Theorem 5, we have w ′.l = (m, h) (4), and can thus derive:
57
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
⌈handlewm h · E · perform op w ′ v⌉ (1),(4),translation
= promptwm · ⌈E⌉ · yieldm (λw k. ⌈f ⌉ w ⌈v⌉ w k)m ̸∈ ⌈E⌉m (3), Theorem 6
−→ (λw k. ⌈f ⌉ w ⌈v⌉ w k) w (guardw (promptwm · ⌈E⌉)) (2), (yield)−→ ⌈f ⌉ w ⌈v⌉ w (guardw (promptwm · ⌈E⌉)= ⌈f ⌉ w ⌈v⌉ w (guardw ⌈handlewm h · E⌉)= ⌈f w v w (guardw (handlewm h · E))⌉
□
B.4.2 Monadic Type Translation.Lemma 33. (Monadic Translation Stable under substitution)⌊σ ⌋[α :=⌊σ ′⌋] = ⌊σ [α :=σ ′]⌋.
Proof. (Of Lemma 33) By induction on σ .case σ = α .⌊α⌋[α :=⌊σ ′⌋]= α[α :=⌊σ ′⌋] by translation
= ⌊σ ′⌋ by substitution
⌊α[α :=σ ′]⌋= ⌊σ ′⌋ by substitution
case σ = β and β , α .
⌊β⌋[α :=⌊σ ′⌋]= β[α :=⌊σ ′⌋] by translation
= β by substitution
⌊β[α :=σ ′]⌋= ⌊β⌋ by substitution
= β by translation
case σ = σ1⇒ ϵ σ2.
⌊σ1⇒ ϵ σ2⌋[α :=⌊σ ′⌋]= (evv ϵ → ⌊σ1⌋ → mon ϵ ⌊σ2⌋)[α :=⌊σ ′⌋] by translation
= evv ϵ → ⌊σ1⌋[α :=⌊σ ′⌋] → mon ϵ (⌊σ2⌋[α :=⌊σ ′⌋]) by substitution
= evv ϵ →(⌊σ1[α :=σ ′]⌋) → mon ϵ (⌈σ2[α :=σ ′]⌉) I.H.
⌊(σ1⇒ ϵ σ2)[α :=σ ′]⌋= ⌈σ1[α :=σ ′]⇒ϵ σ2[α :=σ ′]⌉ by substitution
= evv ϵ → (⌊σ1[α :=σ ′]⌋) → mon ϵ (⌊σ2[α :=σ ′]⌋) by translation
case σ = ∀β . σ1.
⌊∀β . σ1⌋[α :=⌊σ ′⌋]= (∀β . ⌊σ1⌋)[α :=⌊σ ′⌋] by translation
= ∀β . ⌊σ1⌋[α :=⌊σ ′⌋] by substitution
= ∀β . ⌊σ1[α :=σ ′]⌋ I.H.
⌊(∀β . σ1)[α :=σ ′]⌋= ⌊∀β . σ1[α :=σ ′]⌋ by substitution
= ∀β . ⌊σ1[α :=σ ′]⌋ by translation
case σ = c τ1 . . . τn.
58
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
⌊c τ1 . . . τn⌋[α :=⌊σ ′⌋]= (c ⌊τ1⌋ . . . ⌊τn⌋)[α :=⌊σ ′⌋] by translation
= c (⌊τ1⌋[α :=⌊σ ′⌋]) . . . (⌊τn⌋[α :=⌊σ ′⌋]) by substitution
= c (⌊τ1[α :=σ ′]⌋) . . . (⌊τn[α :=σ ′]⌋) by I.H.
⌊(c τ1 . . . τn)[α :=σ ′]⌋= ⌊c τ1[α :=σ ′] . . . τn[α :=σ ′]⌋ by substitution
= c (⌊τ1[α :=σ ′]⌋) . . . (⌊τn[α :=σ ′]⌋) by translation
□
B.4.3 Substitution.Lemma 34. (Monadic Translation Variable Substitution)1. If Γ1, x : σ , Γ2 ⊩val v1 : σ1 ⇝ v ′
1, and Γ1 , Γ2 ⊩val v : σ ⇝ v ′ ,
then Γ1, Γ2 ⊩val v1 [x:= v] : σ1 ⇝ v ′1[x:=v ′] .
2. If Γ1, x : σ , Γ2 ; w; w ′ ⊩ e1 : σ1 | ϵ ⇝ e′1and Γ1 , Γ2 ⊩val v : σ ⇝ v ′,
then Γ1, Γ2 ; w [x := v]; w ′[x:=v ′] ⊩ e1 [x:= v] : σ1 | ϵ ⇝ e′1[x:=v ′].
3. If Γ1, x :σ , Γ2 ⊩ops { op1→ f1, . . ., opn→ fn } : hndl ϵ σ1 | ϵ ⇝ e and Γ1, Γ2 ⊩val v : σ ⇝ v ′,
then Γ1, Γ2⊩ops ({ op1→ f1, . . ., opn→ fn })[x:=v] : hndl ϵ σ1 | ϵ ⇝ e[x:=v ′].
4. If Γ1, x :σ , Γ2 ; w ; w ′ ⊩ec E : σ1→ σ2 | ϵ ⇝ g and Γ1 , Γ2 ⊩val v : σ ⇝ v ′ ,then Γ1, Γ2 ; w[x:=v] ; w ′[x:=v ′] ⊩ec E [x:=v] : σ1→ σ2 | ϵ ⇝ g[x:=v ′].
Proof. (Of Lemma 34) Part 1 By induction on typing.
case v1 = x.σ = σ1 mval
Γ1, x : σ , Γ2 ⊩val x : σ ⇝ x given
Γ1 , Γ2 ⊩val v : σ1 ⇝ v ′ given
case v1 = y where y , x.v1[x:=v] = y by substitution
v ′1[x:=v ′] = y by substitution
y : σ1 ∈ Γ1, Γ2 mvar
Γ1, Γ2 ⊩val y : σ1 ⇝ y mvar
case v1 = λϵ z : evv ϵ, y : σ2. e .Γ1, x :σ , Γ2 ⊩val λϵ z : evv ϵ, y : σ2. e : σ1 ⇝ λz x . e′ given
σ1 = σ2⇒ϵ σ3 mabs
(Γ1, x :σ , Γ2, z : evv ϵ, y : σ2) ; z; z ⊩ e : σ3 | ϵ ⇝ e′ above
Γ1 , Γ2 ⊩val v : σ ⇝ v ′ given
Γ1 , Γ2, z : evv ϵ, y : σ2 ⊩val v : σ ⇝ v ′ weakening
(Γ1, Γ2, z : evv ϵ, y : σ2) ; z; z ⊩ e[x:=v] : σ3 | ϵ ⇝ e′[x:=v ′] Part 2
Γ1, Γ2 ⊩val λϵ z : evv ϵ, y : σ2. e[x:=v] : σ1 ⇝ λz x . e′[x:=v ′] mabs
case v1 = guardw E σ1.
Γ1, x :σ , Γ2⊩val guardw E σ2 : σ1 ⇝ guard w′ e′ given
σ1 = σ2⇒ϵ σ3 mguard
Γ1, x :σ , Γ2 ; w ;w ′ ⊩ec E : σ2→ σ3 | ϵ ⇝ e′ above
Γ1, x :σ , Γ2 ⊩val w : evv ϵ ⇝ w ′ above
Γ1, Γ2 ; w[x:=v]; w ′[x:=v ′] ⊩ E [x:=v] : σ2→ σ3 | ϵ ⇝ e′[x:=v ′] Part 4
Γ1, Γ2 ⊩val w[x:=v] : evv ϵ ⇝ w ′[x:=v ′] I.H.
Γ1, Γ2⊩val guardw[x:=v] E[x:=v] σ2 : σ2⇒ϵ σ3 ⇝ guard w′[x:=v ′] e′[x:=v ′] mguard
59
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
case v1 = Λα . v2.
Γ1, x :σ , Γ2⊩val Λα . v2 : σ1 ⇝ Λα . v ′2
given
σ1 = ∀α . σ2 mtabs
Γ1, x :σ , Γ2⊩val v2 : σ2 above
Γ1, Γ2⊩val v2[x:=v] : σ2 ⇝ v ′2[x:=v ′] I.H.
Γ1, Γ2⊩val Λα . v2[x:=v] : ∀α · σ2 ⇝ Λα . v ′2[x:=v ′] mtabs
case v1 = perform op σ .Γ1, x :σ , Γ2 ⊩val perform op σ : σ1 ⇝ performop [⟨l | µ⟩, ⌊σ ⌋] given
σ1 = σ2[α :=σ ]⇒ ⟨l | µ⟩ σ3[α :=σ ] mperform
op : ∀α . σ2→ σ3 ßΣ(l) above
(perform op σ )[x:=v] = perform op σ by substitution
Γ1, Γ2 ⊩val perform op σ : σ1 ⇝ performop [⟨l | µ⟩, ⌊σ ⌋] mperform
case v1 = handlerϵ h.Γ1, x :σ , Γ2⊩val handlerϵ h : σ1 ⇝ handler l [ϵ, ⌊σ ⌋] h′ given
σ1 = (()⇒ ⟨l | ϵ⟩ σ )⇒ϵ σ mhandler
Γ1, x :σ , Γ2⊩ops h : hndl ϵ σ | ϵ ⇝ h′ above
Γ1, Γ2⊩ops h[x:=v] : hndl ϵ σ | ϵ ⇝ h′[x:=v ′] Part 3
Γ1, Γ2⊩val handlerϵ h[x:=v] : σ1 ⇝ handler l [ϵ, ⌊σ ⌋] h′[x:=v ′] mhandler
Part 2 By induction on typing.
case e1 = v1.
Γ1, x :σ , Γ2 ; w ; w ′ ⊩ v1 : σ1 | ϵ ⇝ v ′1
given
Γ1, x :σ , Γ2 ⊩val v1 : σ1 ⇝ v ′1
mval
Γ1, Γ2 ⊩val v1[x:=v] : σ1 ⇝ v ′1[x:=v ′] Part 1
Γ1, Γ2; w [x:=v]; w ′[x:=v ′]⊩val v1[x:=v] : σ1 | ϵ ⇝ v ′1[x:=v ′] mval
case e1 = e2 w e3.
Γ1, x :σ , Γ2;w;w ′ ⊩ e2 w e3 : σ1 | ϵ ⇝ e′2▷ (λf . e′
3▷ f w ′) given
Γ1, x :σ , Γ2;w;w ′ ⊩ e2 :σ2⇒ϵ σ1 | ϵ ⇝ e′2
mapp
Γ1, x :σ , Γ2;w;w ′ ⊩ e3 :σ2 | ϵ ⇝ e′3
above
Γ1, Γ2;w[x:=v];w ′[x:=v ′] ⊩ e2[x:=v] :σ2⇒ϵ σ1 | ϵ ⇝ e′2[x:=v ′] I.H.
Γ1, Γ2;w[x:=v];w ′[x:=v ′] ⊩ e3[x:=v] :σ2 | ϵ ⇝ e′2[x:=v ′] I.H.
Γ1, Γ2;w[x:=v];w ′[x:=v ′] ⊩ e2[x:=v] w[x:=v] e3[x:=v] : σ1 | ϵ mapp
⇝ e′2[x:=v ′] ▷ (λf . e′
3[x:=v ′] ▷ f w ′[x:=v ′])
case e1 = e2 [σ2].
Γ1, x :σ , Γ2;w;w ′ ⊩ e2 [σ2] : σ1 | ϵ ⇝ e′2▷ (λx . pure (x [⌊σ2⌋])) given
σ1 = σ3 [α :=σ2] mtapp
Γ1, x :σ , Γ2;w;w ′ ⊩ e2 : ∀α . σ3 | ϵ ⇝ e′2
above
Γ1, Γ2;w[x:=v];w[x:=v ′] ⊩ e2[x:=v] : ∀α . σ3 | ϵ ⇝ e′2[x:=v ′] I.H.
Γ1, Γ2;w[x:=v];w[x:=v ′] ⊩ e2[x:=v] [σ2] : σ3[α :=σ2] | ϵ mtapp
⇝ e′2[x:=v ′] ▷ (λx . pure (x [⌊σ2⌋]))
case e1 = handlewm h e2.
60
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
Γ1, x :σ , Γ2;w;w ′ ⊩ handlewm h e2 : σ1 | ϵ ⇝ prompt m w′ e′2
given
Γ1, x :σ , Γ2 ⊩ops h : hndϵ σ1 | ϵ ⇝ h′ mhandle
Γ1, x :σ , Γ2; ⟨⟨l : (m, h) | w⟩⟩; ⟨⟨l : (m, h′) | w ′⟩⟩ ⊩ e2 : σ1 | ⟨l | ϵ⟩ ⇝ e′2
above
h ∈ Σ(l) above
Γ1, Γ2; (⟨⟨l : (m, h) | w⟩⟩)[x:=v]; (⟨⟨l : (m, h′) | w ′⟩⟩)[x:=v ′] I.H.
⊩ e2[x:=v] : σ1 | ⟨l | ϵ⟩ ⇝ e′2[x:=v ′]
Γ1, Γ2 ⊩ops h[x:=v] : hndϵ σ1 | ϵ ⇝ h′[x:=v ′] Part 3
Γ1, Γ2; w[x:=v];w ′[x:=v ′] ⊩ handlew[x:=v]m h[x:=v] e2[x:=v] : σ1 | ⟨ϵ⟩ mhandle
⇝ prompt m w′[x:=v ′] e′2[x:=v ′]
Part 3
Γ1, x :σ , Γ2 ⊩ops { op1→ f1, . . ., opn→ fn } : hndl ϵ σ1 | ϵ ⇝ {op1
→ f ′1, . . ., opn→ f ′n } given
Γ1, x :σ , Γ2 ⊩val fi : ∀α . σ1⇒ ϵ (σ2⇒ ϵ σ )⇒ ϵ σ ⇝ f ′i mops
opi : ∀α . σ1→ σ2 ∈ Σ(l) α ̸∩ ftv(ϵ σ ) above
Γ1, Γ2 ⊩val fi[x:=v] : ∀α . σ1⇒ ϵ (σ2⇒ ϵ σ )⇒ ϵ σ ⇝ f ′i [x:=v ′] Part 1
Γ1, Γ2 ⊩ops { op1→ f1[x:=v], . . ., opn→ fn[x:=v] } : hndl ϵ σ1 | ϵ mops
⇝ {op1→ f ′
1[x:=v ′], . . ., opn→ f ′n [x:=v ′]}
Part 4 By induction on typing.
case E = □.Γ1, x :σ , Γ2 ; w ; w ′ ⊩ec □ : σ1→ σ2 | ϵ ⇝ id given
σ1 = σ2 mon-cempty
□[x:=v] = □ by substitution
Γ1, Γ2 ; w[x:=v] ; w ′[x:=v ′] ⊩ec □ : σ1→ σ1 | ϵ ⇝ id mon-cempty
case E = E1 w e .Γ1, x :σ , Γ2 ; w; w ′ ⊩ec E1 w e : σ1→ σ2 | ϵ ⇝ (λf . e′ ▷ f w) • g given
Γ1, x :σ , Γ2 ; w; w ′ ⊩ec E1 : σ1→ (σ3⇒ ϵ σ2) | ϵ ⇝ g mon-capp1
Γ1, x :σ , Γ2 ; w; w ′ ⊩ e : σ3 | ϵ ⇝ e′ above
Γ1, Γ2 ; w[x:=v]; w ′[x:=v ′] ⊩ec E1[x:=v] : σ1→ (σ3⇒ ϵ σ2) | ϵ ⇝ g[x:=v ′] I.H.
Γ1, Γ2 ; w[x:=v]; w ′[x:=v ′] ⊩ e[x:=v] : σ3 | ϵ ⇝ e′[x:=v ′] Part 2
Γ1, Γ2; w[x:=v]; w ′[x:=v ′] ⊩ec E1[x:=v] w[x:=v] e[x:=v] : σ1→ σ2 | ϵ mon-capp1
⇝ (λf . e′[x:=v ′] ▷ f w[x:=v ′]) • g[x:=v ′]case E = v1 w E1.
Γ1, x :σ , Γ2 ; w; w ′ ⊩ec v1 w E1 : σ1→ σ2 | ϵ ⇝ v ′1w ′ • g given
Γ1, x :σ , Γ2 ; w;w ′ ⊩ec E1 : σ1→ σ3 | ϵ ⇝ g mon-capp2
Γ1, x :σ , Γ2 ⊩val v1 : σ3⇒ϵ σ2 ⇝ v ′1
above
Γ1, Γ2 ; w[x:=v]; w ′[x:=v ′] ⊩ec E1[x:=v] : σ1→ σ3 | ϵ ⇝ g[x:=v ′] I.H.
Γ1, Γ2 ⊩val v1[x:=v] : σ3⇒ϵ σ2 ⇝ v ′1[x:=v ′] Part 2
Γ1, Γ2; w[x:=v]; w ′[x:=v ′] ⊩ec v1[x:=v] w[x:=v] E1[x:=v] : σ1→ σ2 | ϵ mon-capp2
⇝ v ′1[x:=v ′] w ′[x:=v ′]
case E = E1 [σ ].
Γ1, x :σ , Γ2 ; w ;w ′ ⊩ec E1 [σ ] : σ1→ σ2 | ϵ ⇝ (λx . pure x) • g given
Γ1, x :σ , Γ2 ; w ;w ′ ⊩ec E1 : σ1→ ∀α . σ3 | ϵ ⇝ g mon-ctapp
σ2 = σ3[α :=σ ] above
Γ1, Γ2 ; w[x:=v] ⊩ec E1[x:=v] : σ1→ ∀α . σ3 | ϵ ⇝ g[x:=v ′] I.H.
Γ1, x :σ , Γ2; w[x:=v] ⊩ec E1[x:=v] [σ ] : σ1→ σ2 | ϵ ⇝ (λx . pure x) • g[x:=v ′] mon-ctapp
case E = handlewm h E1.
61
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
Γ1, x :σ , Γ2;w;w ′ ⊩ec handlewm h E : σ1→ σ2 | ϵ ⇝ prompt m w ′ ◦ g given
Γ1, x :σ , Γ2;w;w ′ ⊩ops h : hndl ϵ σ2 | ϵ ⇝ h′ above
Γ1, x :σ , Γ2; ⟨⟨l : (m, h) | w⟩⟩; ⟨⟨l : (m, h′) | w ′⟩⟩ ⊩ec E : σ1→ σ2 | ⟨l | ϵ⟩ ⇝ g above
Γ1, Γ2; ⟨⟨l : (m, h[x:=v]) | w[x:=v]⟩⟩; ⟨⟨l : (m, h′[x:=v ′]) | w ′[x:=v ′]⟩⟩ I.H.
⊩ec E[x:=v] : σ1→ σ2 | ⟨l | ϵ⟩ ⇝ g[x:=v ′]Γ1, Γ2 ⊩ops h[x:=v] : hndl ϵ σ2 | ϵ ⇝ h′[x:=v ′] ] Part 3
Γ1, Γ2;w[x:=v];w ′[x:=v ′] ⊩ec handlew[x:=v]m h[x:=v] E[x:=v] : σ1→ σ2 | ϵ mon-chandle
⇝ prompt m w′[x:=v ′] ◦ g[x:=v ′]□
Lemma 35. (Monadic Translation Type Variable Substitution)1. If Γ ⊩val v : σ ⇝ v ′ and⊢wf σ1 : k,then Γ[αk
:=σ1] ⊩val v[αk:=σ1] : σ [αk
:=σ1] ⇝ v ′[αk:=⌊σ1⌋].
2. If Γ;w;w ′ ⊩ e : σ | ϵ ⇝ e′ and⊩wf σ1 : k,then Γ[αk
:=σ1];w[αk:=σ1];w ′[α ⌊k⌋ :=⌊σ1⌋] ⊩ e[αk
:=σ1] : σ [αk:=σ1] | ϵ ⇝ e′[αk
:=⌊σ1⌋].
3. If Γ ⊩ops h : σ | l | ϵ ⇝ h′ and⊢wf σ1 : k,then Γ[αk
:=σ1] ⊩ops h[αk:=σ1] : σ [αk
:=σ1] | l | ϵ ⇝ v ′[αk:=⌊σ1⌋].
4. If Γ;w;w ′ ⊩ E : σ1→ σ2 | ϵ ⇝ g and⊢wf σ1 : k,then Γ[αk
:=σ1];w[αk:=σ1];w ′[αk = ⌊σ1⌋] ⊩ E[αk
:=σ1] : σ1[αk:=σ1] → σ2[α
k:=σ1] ⇝ v ′[αk
:=⌊σ1⌋].
Proof. (Of Lemma 35) Part 1 By induction on typing.
case v = x.Γ ⊩val x : σ ⇝ x given
x :σ ∈ Γ mvar
x :σ [α :=σ1] ∈ Γ[α :=σ1] follows
Γ[α :=σ1] ⊩val x : σ [α :=σ1] ⇝ x mvar
case v = λϵ z : evv ϵ, y : σ2. e .Γ ⊩val λϵ z : evv ϵ, y : σ2. e : σ2⇒ϵ σ3 ⇝ λz x . e′ given
(Γ, z : evv ϵ, y : σ2) ; z; z ⊩ e : σ3 | ϵ ⇝ e′ mabs
(Γ[α :=σ1] z : evv ϵ, y : σ2[α :=σ1]) ; z; z ⊩ e[α :=σ1] : σ3[α :=σ1] | ϵ ⇝ e′[α :=⌊σ1⌋] Part 2
Γ ⊩val λϵ z : evv ϵ, y : σ2[α :=σ1]. e[α :=σ1] : σ2[α :=σ1]⇒ϵ σ3[α :=σ1] ⇝ λz x . e′[α :=⌊σ1⌋] mabs
case v = guardw E σ2.
Γ⊩val guardw E σ2 : σ2⇒ϵ σ3 ⇝ guard w ′ e′ given
Γ ; w ;w ′ ⊩ec E : σ2→ σ3 | ϵ ⇝ e′ mguard
Γ ⊩val w : evv ϵ ⇝ w ′ above
Γ[α :=σ1] ; w[α :=σ1]; w ′[α :=σ1] ⊩ E [α :=σ1] : σ2[α :=σ1] → σ3[α :=σ1] | ϵ ⇝ e′[α :=⌊σ1⌋] Part 4
Γ[α :=σ1] ⊩val w[α :=σ1] : evv ϵ ⇝ w ′[α :=⌊σ1⌋] I.H.
Γ[α :=σ1] ⊩val guardw[α :=σ1] E[α :=σ1] σ2 : σ2[α :=σ1]⇒ϵ σ3[α :=σ1] mguard
⇝ guard w′[α :=⌊σ1⌋] e′[α :=⌊σ1⌋]
case v = Λα . v2.
Γ⊩val Λα . v2 : ∀α . σ2 ⇝ Λα . v ′2
given
Γ⊩val v2 : σ2 mtabs
Γ[α :=σ1]⊩val v2[α :=σ1] : σ2[α :=σ1] ⇝ v ′2[α :=⌊σ1⌋] I.H.
Γ[α :=σ1]⊩val Λα . v2[α :=σ1] : ∀α · σ2 ⇝ Λα . v ′2[α :=⌊σ1⌋] mtabs
case v = perform op σ .
62
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
Γ ⊩val perform op σ : σ2[α :=σ ]⇒ ⟨l | µ⟩ σ3[α :=σ ] ⇝ performop [⟨l | µ⟩, ⌊σ ⌋] given
op : ∀α . σ2→ σ3 ∈ Σ(l) mperform
(perform op)[α :=σ1] = perform op by substitution
Γ[α :=σ1] ⊩val perform op σ [α :=σ1] ] : σ2[α :=(σ [α :=σ ])]⇒ ⟨l | µ⟩ σ3[α :=(σ [α :=σ1])] mperform
⇝ performop [⟨l | µ⟩, ⌊σ ⌋]σ2[α :=(σ [α :=σ1])]
= (σ2[α :=σ1])[α :=(σ [α :=σ1])] α fresh to σ2
= (σ2[α :=σ ])[α :=σ1] by substitution
σ3[α :=(σ [α :=σ1])] = (σ3[α :=σ ])[αk:=σ1] similarly
⌊σ [α :=σ1]⌋ = ⌊σ ⌋[α :=⌊σ1⌋] Lemma 15
Γ[α :=σ1] ⊩val perform op σ [α :=σ1] therefore
: (σ2[α :=σ ])[α :=σ1]⇒⟨l | µ⟩ (σ3[α :=σ ])[α :=σ1]
⇝ performop [⟨l | µ⟩, ⌊σ ⌋[α :=⌊σ1⌋] ]
case v = handlerϵ h.Γ ⊩val handlerϵ h : σ2 ⇝ handler l [ϵ, ⌊σ ⌋] h′ given
σ2 = (()⇒ ⟨l | ϵ⟩ σ )⇒ϵ σ mhandler
Γ⊩ops h : hndl ϵ σ | ϵ ⇝ h′ above
Γ[α :=σ1]⊩ops h[α :=σ1] : hndl ϵ σ [α :=σ1] | ϵ ⇝ h′[α :=⌊σ1⌋] Part 3
⌊σ [α :=σ1]⌋ = ⌊σ ⌋[α :=⌊σ1⌋] Lemma 15
Γ[α :=σ1]⊩val handlerϵ h[α :=σ1] : σ2[α :=σ1] ⇝ handler l [ϵ, ⌊σ ⌋[α :=⌊σ1⌋] ] h′[α :=⌊σ1⌋] mhandler
Part 2 By induction on typing.
case e = v.Γ ; w ; w ′ ⊩ v : σ | ϵ ⇝ v ′ given
Γ ⊩val v : σ ⇝ v ′ mval
Γ[α :=σ1] ⊩val v[α :=σ1] : σ [α :=σ1] ⇝ v ′[α :=⌊σ1⌋] Part 1
Γ[α :=σ1]; w[α :=σ1] ; w ′[α :=⌊σ1⌋] ⊩val v1[α :=σ1] : σ [α :=σ1] | ϵ ⇝ v ′[α :=⌊σ1⌋] mval
case e = e2 w e3.
Γ;w;w ′ ⊩ e2 w e3 : σ3 | ϵ ⇝ e′2▷ (λf . e′
3▷ f w ′) given
Γ;w;w ′ ⊩ e2 :σ2⇒ϵ σ3 | ϵ ⇝ e′2
mapp
Γ;w;w ′ ⊩ e3 :σ2 | ϵ ⇝ e′3
above
Γ[α :=σ1];w[α :=σ1];w ′[α :=⌊σ1⌋] ⊩ e2[α :=σ1] :σ2[α :=σ1]⇒ϵ σ3[α :=σ1] | ϵ ⇝ e′2[α :=⌊σ1⌋] I.H.
Γ[α :=σ1];w[α :=σ1];w ′[α :=⌊σ1⌋] ⊩ e3[α :=σ1] :σ2[α :=σ1] | ϵ ⇝ e′3[α :=⌊σ1⌋] I.H.
Γ[α :=σ1];w[α :=σ1];w ′[α :=⌊σ1⌋] ⊩ e2[α :=σ1] w[α :=σ1] e3[α :=σ1] : σ3[α :=σ1] | ϵ mapp
⇝ e′2[α :=⌊σ1⌋] ▷ (λf . e′3[α :=⌊σ1⌋] ▷ f w ′[α :=⌊σ1⌋])
case e = e2 [σ2].
Γ;w;w ′ ⊩ e2 [σ2] : σ1 | ϵ ⇝ e′2▷ (λx . pure (x [⌊σ2⌋])) given
σ1 = σ3 [α :=σ2] mtapp
Γ;w;w ′ ⊩ e2 : ∀β . σ3 | ϵ ⇝ e′2
above
Γ[α :=σ1];w[α :=σ1];w[α :=⌊σ1⌋] ⊩ e2[α :=σ1] : ∀β . σ3[α :=σ1] | ϵ ⇝ e′2[α :=⌊σ1⌋] I.H.
(σ3[α :=σ1])[β :=(σ2[α :=σ1]) ] = (σ3[β :=σ2])[α :=σ1] by substitution
⌊σ2[α :=σ1]⌋ = ⌊σ2⌋[α :=⌊σ1⌋] Lemma 33
Γ[α :=σ1];w[α :=σ1];w[α :=⌊σ1⌋] ⊩ e2[α :=σ1] [σ2[α :=σ1] ] : (σ3[β :=σ2])[α :=σ1] | ϵ mtapp
⇝ e′2[α :=⌊σ1⌋] ▷ (λx . pure (x [⌊σ2⌋[α :=⌊σ1⌋]))
case e = handlewm h e2.
63
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
Γ;w;w ′ ⊩ handlewm h e2 : σ | ϵ ⇝ prompt m w′ e′2
given
Γ ⊩ops h : hndϵ σ | ϵ ⇝ h′ mhandle
Γ; ⟨⟨l : (m, h) | w⟩⟩; ⟨⟨l : (m, h′) | w ′⟩⟩ ⊩ e2 : σ | ⟨l | ϵ⟩ ⇝ e′2
above
h ∈ Σ(l) above
Γ[α :=σ1]; (⟨⟨l : (m, h) | w⟩⟩)[α :=σ1]; (⟨⟨l : (m, h′) | w ′⟩⟩)[α :=⌊σ1⌋] I.H.
$\qquad \qquad
Γ[α :=σ1] ⊩ops h[α :=σ1] : σ [α :=σ1] | l | ϵ | ϵ ⇝ h′[α :=⌊σ1⌋] Part 3
Γ[α :=σ1]; w[α :=σ1];w ′[α :=⌊σ1⌋] ⊩ handlew[α :=σ1]m h[α :=σ1] e2[α :=σ1] : σ | ⟨ϵ⟩ mhandle
⇝ prompt m w′[α :=⌊σ1⌋] e′2[α :=⌊σ1⌋]
Part 3
Γ ⊩ops { op1→ f1, . . ., opn→ fn } : σ | l | ϵ | ϵ ⇝ {op
1→ f ′
1, . . ., opn→ f ′n } given
Γ ⊩val fi : ∀α . σ3⇒ ϵ (σ2⇒ ϵ σ )⇒ ϵ σ ⇝ f ′i mops
opi : ∀α . σ3→ σ2 ∈ Σ(l) α ̸∩ ftv(ϵ σ ) above
Γ[α :=σ1] ⊩val fi[α :=σ1] : ∀α . σ3⇒ ϵ (σ2⇒ ϵ σ [α :=⌊σ1⌋])⇒ ϵ σ [α :=⌊σ1⌋] ⇝ f ′i [α :=⌊σ1⌋] Part 1
Γ[α :=σ1] ⊩ops { op1→ f1[α :=σ1], . . ., opn→ fn[α :=σ1] } : σ [α :=⌊σ1⌋] | l | ϵ | ϵ mops
⇝ {op1→ f ′
1[α :=⌊σ1⌋], . . ., opn→ f ′n [α :=⌊σ1⌋]}
Part 4 By induction on typing.
case E = □.Γ[α :=σ1] ; w ; w ′ ⊩ec □ : σ1→ σ2 | ϵ ⇝ id given
σ1 = σ2 mon-cempty
□[α :=σ1] = □ by substitution
Γ1, Γ2 ; w[α :=σ1] ; w ′[α :=⌊σ1⌋] ⊩ec □ : σ1[α :=σ1] → σ1[α :=σ1] | ϵ ⇝ id mon-cempty
case E = E1 w e .Γ ; w; w ′ ⊩ec E1 w e : σ → σ2 | ϵ ⇝ (λf . e′ ▷ f w) • g given
Γ ; w; w ′ ⊩ec E1 : σ → (σ3⇒ ϵ σ2) | ϵ ⇝ g mon-capp1
Γ ; w; w ′ ⊩ e : σ3 | ϵ ⇝ e′ above
Γ[α :=σ1] ; w[α :=σ1]; w ′[α :=⌊σ1⌋] ⊩ec E1[α :=σ1] I.H.
: σ [α :=σ1] → (σ3[α :=σ1]⇒ ϵ σ2[α :=σ1]) | ϵ ⇝ g[α :=⌊σ1⌋]
Γ[α :=σ1] ; w[α :=σ1]; w ′[α :=⌊σ1⌋] ⊩ e[α :=σ1] : σ3[α :=σ1] | ϵ ⇝ e′[α :=⌊σ1⌋] Part 2
Γ[α :=σ1] ; w[α :=σ1]; w ′[α :=⌊σ1⌋] ⊩ec E1[α :=σ1] w[α :=σ1] e[α :=σ1] mon-capp1
: σ [α :=σ1] → σ2[α :=σ1] | ϵ ⇝ (λf . e′[α :=⌊σ1⌋] ▷ f w[α :=⌊σ1⌋]) • g[α :=⌊σ1⌋]
case E = v1 w E1.
Γ; w; w ′ ⊩ec v1 w E1 : σ → σ2 | ϵ ⇝ v ′1w ′ • g given
Γ; w; w ′ ⊩ec E1 : σ → σ3 | ϵ ⇝ g mon-capp2
Γ ⊩val v1 : σ3⇒ϵ σ2 ⇝ v ′1
above
Γ[α :=σ1] ; w[α :=σ1]; w ′[α :=⌊σ1⌋] ⊩ec E1[α :=σ1] : σ [α :=σ1] → σ3[α :=σ1] | ϵ ⇝ g[α :=⌊σ1⌋] I.H.
Γ[α :=σ1] ⊩val v1[α :=σ1] : σ3⇒ϵ σ2 ⇝ v ′1[α :=⌊σ1⌋] Part 2
Γ[α :=σ1] ; w[α :=σ1]; w ′[α :=⌊σ1⌋] ⊩ec v1[α :=σ1] w[α :=σ1] E1[α :=σ1] mon-capp2
: σ [α :=σ1] → σ2[α :=σ1] | ϵ ⇝ v ′1[α :=⌊σ1⌋] w ′[α :=⌊σ1⌋]
case E = E1 [σ ].
64
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
Γ ; w ;w ′ ⊩ec E1 [σ ] : σ → σ2 | ϵ ⇝ (λx . pure (x [⌊σ ⌋])) • g given
Γ ; w ;w ′ ⊩ec E1 : σ → ∀α . σ3 | ϵ ⇝ g mon-ctapp
σ2 = σ3[α :=σ ] above
Γ[α :=σ1]; w[α :=⌊σ1⌋] ⊩ec E1[α :=σ1] : σ [α :=σ1] → ∀α . σ3[α :=σ1] | ϵ ⇝ g[α :=⌊σ1⌋] I.H.
⌊σ ⌋[α :=⌊σ1⌋] = ⌊σ [α :=σ1]⌋ Lemma 33
Γ[α :=σ1]; w[α :=⌊σ1⌋] ⊩ec E1[α :=σ1] [σ [α :=σ1] ] mon-ctapp
: σ [α :=σ1] → σ2[α :=σ1] | ϵ ⇝ (λx . pure (x ⌊σ ⌋[α :=⌊σ1⌋])) • g[α :=⌊σ1⌋]
case E = handlewm h E1.
Γ;w;w ′ ⊩ec handlewm h E : σ → σ2 | ϵ ⇝ prompt m w′ ◦ g given
Γ;w;w ′ ⊩ops h : σ2 | l | ϵ ⇝ h′ above
Γ; ⟨⟨l : (m, h) | w⟩⟩; ⟨⟨l : (m, h′) | w ′⟩⟩ ⊩ec E : σ → σ2 | ⟨l | ϵ⟩ ⇝ g above
Γ[α :=σ1]; ⟨⟨l : (m, h[α :=σ1]) | w[]⟩⟩; ⟨⟨l : (m, h′[α :=⌊σ1⌋]) | w ′[α :=⌊σ1⌋]⟩⟩ ⊩ec E[α :=⌊σ1⌋] I.H.
: σ [α :=σ1] → σ2[α :=σ1] | ⟨l | ϵ⟩ ⇝ g[α :=⌊σ1⌋]
Γ[α :=σ1] ⊩ops h[α :=σ1] : σ2[α :=σ1] | l | ϵ ⇝ h′[α :=⌊σ1⌋] ] Part 3
Γ[α :=σ1];w[α :=⌊σ1⌋];w ′[α :=⌊σ1⌋] ⊩ec handlew[α :=σ1]m h[α :=σ1] E[α :=σ1] : σ1→ σ2 | ϵ mon-chandle
⇝ prompt m w′[α :=⌊σ1⌋] ◦ g[α :=⌊σ1⌋]
□
B.4.4 Evaluation Context Typing.Lemma 36. (Monadic contexts)If Γ;w ⊩ec E : σ1→ σ2 | ϵ ⇝ g and Γ; ⟨⟨⌈E⌉ | w⟩⟩ ⊩ e : σ1 | ⟨⌈E⌉l | ϵ⟩ ⇝ e′ then Γ;w ⊩ E[e] : σ2 | ϵ(due to Lemma 22) and Γ;w ⊩ E[e] : σ2 | ϵ ⇝ g e′.
Proof. (Of Lemma 36) By induction on the evaluation context typing.
case E = □.Γ;w ⊩ec □ : σ1→ σ1 ⇝ id given
Γ;w ⊩ e : σ1 | ϵ ⇝ e′ given
e′
= id e′ idcase E = E0 w e0.
Γ;w ⊩ec E0 w e0 : σ1→ σ2 | ϵ ⇝ (λf . f w ◁ e′0) • g given
Γ;w ⊩ec E0 : σ1→ (σ3⇒ ϵ σ2) | ϵ ⇝ g above
⌈E0 w e0⌉ = ⌈E0⌉ by definition
⌈E0 w e0⌉l = ⌈E0⌉
lby definition
Γ;w ⊩ E0[e] : σ3⇒ ϵ σ2 | ϵ ⇝ g e′ I.H.
Γ;w ⊩ E0[e] w e0 : σ2 | ϵ ⇝ (λf . f w ◁ e′0) ◁ g e′ mapp
(λf . f w ◁ e′0) ◁ g e′
= ((λf . f w ◁ e′0) • g) e′ by (•)
case E = v w E0.
65
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
Γ;w ⊩ec v w E0 : σ1→ σ2 | ϵ ⇝ (v ′ w) • g given
Γ;w ⊩ec E0 : σ1→ σ3 | ϵ ⇝ g above
⌈v w E0⌉ = ⌈E0⌉ by definition
⌈v w E0⌉l = ⌈E0⌉
lby definition
Γ;w ⊩ E0[e] : σ3 | ϵ ⇝ g e′ I.H.
Γ;w ⊩ v w E0[e] : σ2 | ϵ ⇝ (λf . f w ◁ (g e′)) ◁ (pure[⌊σ3⇒ϵ σ2⌋] v ′) mapp
(λf . f w ◁ (g e′)) ◁ (pure[⌊σ3⇒ϵ σ2⌋] v ′)= (λf . f w ◁ (g e′)) v ′ (◁)= v ′ w ◁ g e′ reduce
= (v ′ w • g) e′ (•)
case E = E0 [σ ].
Γ;w ⊩ec E0 [σ ] : σ1→ σ2[α :=σ ] | ϵ ⇝ (λx . pure (x[⌊σ ⌋])) • g given
Γ;w ⊩ec E0 : σ1→ ∀α . σ2 | ϵ ⇝ g above
⌈E0 [σ ]⌉ = ⌈E0⌉ by definition
⌈E0 [σ ]⌉l = ⌈E0⌉
lby definition
Γ;w ⊩ E0[e] : ∀α . σ2 | ϵ ⇝ g e′ I.H.
Γ;w ⊩ E0[e] [σ ] : σ2[α :=σ ] | ϵ ⇝ (λx . pure (x[⌊σ ⌋])) ◁ (g e′) mtapp
(λx . pure (x[⌊σ ⌋])) ◁ g e′
= (λx . pure (x[⌊σ ⌋]) • g) e′ of (•)
case E = handlewm h E0.
Γ;w ⊩ec handlewm h E0 : σ1→ σ2 | ϵ ⇝ prompt[ϵ, ⌊σ ⌋] m w ◦ g given
Γ; ⟨⟨l : (m, h) | w⟩⟩ ⊩ec E0 : σ1→ σ2 | ⟨l | ϵ⟩ ⇝ g above
⟨⟨⌈handlewm h E0⌉ | w⟩⟩ = ⟨⟨⌈E0⌉ | ⟨⟨l : (m, h) | w⟩⟩⟩⟩ by definition
⟨⌈handlewm h E0⌉l | ϵ⟩ = ⟨⌈E0⌉
l | ⟨l | ϵ⟩ ⟩ by definition
Γ; ⟨⟨⌈E⌉ | w⟩⟩ ⊩ e : σ1 | ⟨⌈E⌉l | ϵ⟩ ⇝ e′ given
Γ; ⟨⟨⌈E0⌉ | ⟨⟨l : (m, h) | w⟩⟩⟩⟩ ⊩ e : σ1 | ⟨⌈E0⌉l | ⟨l | ϵ⟩ ⟩ ⇝ e′ by substitution
Γ; ⟨⟨l : (m, h) | w⟩⟩ ⊩ E0[e] : σ2 | ⟨l | ϵ⟩ ⇝ g e′ I.H.
Γ;w ⊩ handlewm h (E0[e]) : σ2 | ϵ ⇝ prompt[ϵ, ⌊σ ⌋] m w (g e′) mhandle
prompt[ϵ, ⌊σ ⌋] m w (g e′)= (prompt[ϵ, ⌊σ ⌋] m w ◦ g) e′ (◦)
□
Definition 3.Define a certain form of expression r , as r := id | e • r | prompt m w ◦ r .
bm(id) = ∅bm(e • r) = bm(r)bm(prompt m w ◦ r)= bm(r) ∪ { m }
Lemma 37.If Γ;w ⊩ec E : σ1→ σ2 | ϵ ⇝ r .
Proof. (Of Lemma 37) By straightforward induction on the evaluation context typing. □
Lemma 38. ((•) associates with (◦))1. e1
• (e2 ◦ e3) = (e1• e2) ◦ e3.
Proof. (Of Lemma 38)
66
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
(e1• (e2 ◦ e3)) x
= e1 ◁ ((e2 ◦ e3) x) definition of (•)
= e1 ◁ (e2 (e3 x)) definition of (◦)
((e1• e2) ◦ e3) x
= (e1• e2) (e3 x) definition of (◦)
= e1 ◁ (e2 (e3 x)) definition of (•)
□
Lemma 39. ((◦) properties)1. e ◦ id = e.2. id ◦ e = e.
Lemma 40. (Yield hoisting)If m ̸∈ bm(r), then r (yield m f cont) = yield m f (r ◦ cont).
Proof. (Of Lemma 40) By induction on r .case r = id.id (yield m f cont)= yield m f cont by id= yield m f (id ◦ cont) Lemma 39.2
case r = e • r0.
(e • r0) (yield m f cont)= e ◁ (r0 (yield m f cont)) definition of (•)
= e ◁ (yield m f (r0 ◦ cont)) I.H.
= yield m f (e • (r0 ◦ cont)) definition of (◁)= yield m f ((e • r0) ◦ cont) Lemma 38
case r = prompt m1 w ◦ r0.
(prompt m1 w ◦ r0) (yield m f cont)= prompt m1 w (r0 (yield m f cont)) definition of (◦)
= prompt m1 w (yield m f (r0 ◦ cont)) I.H.
(m ̸∈ bop( prompt m1 w ◦ r0)) given
(m , m1 )) follows
= yield m f (prompt m1 w ◦ (r0 ◦ cont)) definition of prompt= yield m f ((prompt m1 w ◦ r0) ◦ cont) (◦) is associative□
Lemma 41.If m ̸∈ ⌈E⌉m , and Γ; w ⊩ E : σ1→ σ2 ⇝ r , then m ̸∈ bm(r).
Proof. (Of Lemma 41) By a straightforward induction on the evaluation context translation. The
only interesting case is mon-chandle,
Γ ; w ⊩ hanglewm1
h E : σ1→ σ | ϵ ⇝ prompt[ϵ,σ ] m w ◦ r given
Γ ; ⟨⟨l : (m, h′) | w⟩⟩ ⊩ E : σ1→ σ | ⟨l | ϵ⟩ ⇝ r mon-chandle
m ̸∈ bm(r) I.H.
m ̸∈ ⌈handlewm1
h E⌉m given
m , m1 Follows
m ̸∈ bm(prompt[ϵ,σ ] m w ◦ r) Follows
□
67
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
B.4.5 Translation Coherence.Proof. (Of Theorem 11) Apply Lemma 42, with w = w ′ = ⟨⟨⟩⟩. □
Lemma 42. (Coherence of the Monadic Translation)If∅;w;w ′ ⊩ e1 : σ | ⟨⟩ ⇝ e′
1and e1 −→ e2, then also∅;w;w ′ ⊩ e2 : σ | ⟨⟩ ⇝ e′
2where e′
1−→∗ e′
2.
Proof. (Of Theorem 42) Induction on the operational rules.
case (λϵ z : evv ϵ, x :σ . e) w v −→ e[z:=w, x:=v].∅; w; w ′ ⊩ (λϵ z : evv ϵ, x :σ . e) w v : σ | ϵ ⇝ (λf . f w ′ ◁ pure v ′) ◁ (pure (λz x . e′)) given
(λf . f w ′ ◁ pure v ′) ◁ (pure (λz x . e′))−→ (λf . f w ′ ◁ pure v ′) (λz x . e′) (◁)−→ (λz x . e′) w ′ ◁ pure v ′ reduces
−→ (λz x . e′) w ′ v ′ (◁)−→ e′[z:=w ′, x:=v ′] (◁)z : evv ϵ, x :σ ; w; w ′ ⊩ e : σ1⇒ϵ σ | ϵ ⇝ e′ mapp,mabs
∅;w;w ′ ⊩ e[z:=w, x:=v] : σ | ϵ ⇝ e′[z:=w ′, x:=v ′] Lemma 34
case (Λαk . v) [σ ] −→ v[α :=σ ].
∅; w; w ′ ⊩ (Λαk . v) [σ ] : σ2[α :=σ ] | ϵ ⇝ (λx . pure (x [⌊σ ⌋])) ◁ pure (Λα . v ′) given
(λx . pure (x [⌊σ ⌋])) ◁ pure (Λα . v ′)7−→ (λx . pure (x [⌊σ ⌋])) (Λα . v ′) (◁)−→ (pure ((Λα . v ′) [⌊σ ⌋])) (app)7−→ pure (v ′[α :=σ ])∅;w;w ′ ⊩ v[α :=σ ] :σ2[α :=σ ] | ϵ ⇝ pure (v ′[α :=σ ]) Lemma 35
case (handlerϵ h) w v −→ handlewm h (v ⟨⟨l : (m, h) | w⟩⟩ ()) with m unique.
∅;w;w ′ ⊩ (handlerϵ h) w v : σ | ϵ given
⇝ (λf . f w ′ ◁ pure v) ◁ pure (handler l [ϵ,σ ] h′)(λf . f w ′ ◁ pure v ′) ◁ pure (handler l [ϵ,σ ] h′)−→ (λf . f w ′ ◁ pure v ′) (handler l [ϵ,σ ] h′) (◁)
−→ (handler l [ϵ,σ ] h′) w ′ ◁ pure v ′ reduces
−→ (handler l [ϵ,σ ] h′) w ′ v ′ (◁)−→ freshm (λm. prompt[ϵ,σ ] m w ′ (v ′ ⟨⟨l : (m, h) | w ′⟩⟩ ()) handler−→ prompt[ϵ,σ ] m w ′ (v ′ ⟨⟨l : (m, h) | w ′⟩⟩ () given m unique
∅;w;w ′ ⊩ handlewm h (v ⟨⟨l : (m, h) | w⟩⟩ ()) : σ | ϵ given
⇝ prompt[ϵ,σ ] m w ′ ( (λf . f ⟨⟨l : (m, h) | w ′⟩⟩ ◁ pure () ) ◁ pure v ′)prompt[ϵ,σ ] m w ′ ( (λf . f ⟨⟨l : (m, h) | w ′⟩⟩ ◁ pure () ) ◁ pure v ′)7−→ prompt[ϵ,σ ] m w ′ ( (λf . f ⟨⟨l : (m, h) | w ′⟩⟩ ◁ pure () ) v ′) (◁)7−→ prompt[ϵ,σ ] m w ′ (v ′ ⟨⟨l : (m, h) | w ′⟩⟩ ◁ pure () ) reduces
7−→ prompt[ϵ,σ ] m w ′ (v ′ ⟨⟨l : (m, h) | w ′⟩⟩ () ) (◁)
case handlewm h · v −→ v.∅; w; w ′ ⊩ handlewm h · v : σ | ϵ ⇝ prompt[ϵ,σ ] m w ′ (pure v ′) given
prompt[ϵ,σ ] m w ′ (pure v ′)−→ pure v ′ prompt
case handlewm h · E · perform op σ w1 v −→ f w v w k with (op→ f ) ∈ h, op ̸∈ bop(E),and k = guardw (handlewm h · E).From the assumption:
∅;w;w ′ ⊩ handlewm h · E · perform op σ w1 v ⇝ e′1and
68
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
∅;w;w ′ ⊩ f w v w k ⇝ (λf0. f0 w ′ ◁ (pure k′)) ◁ ((λf1. f1 w ′ ◁ (pure v ′)) ◁ (pure f ′))with k′ = guard w′ (prompt m w′ ◦ g) where ∅;w;w ′⊩ec E ⇝ g.
We can simplify the translation of f w v w k as:
(λf0. f0 w ′ ◁ (pure k′)) ◁ ((λf1. f1 w ′ ◁ (pure v ′)) ◁ (pure f ′))7−→ (λf0. f0 w ′ ◁ (pure k′)) ◁ ((λf1. f1 w ′ ◁ (pure v ′)) ◁ pure f ′)7−→ (λf0. f0 w ′ ◁ (pure k′)) ◁ (f ′ w ′ ◁ (pure v ′))7−→ (λf0. f0 w ′ ◁ (pure k′)) ◁ (f ′ w ′ v ′)
∅;w;w ′ ⊩ handlewm h · E · perform op σ w1 v ⇝ e′1
given
e′1
= prompt m w ′ (g ((λf . f w ′1◁ pure v ′) ◁ pure (performop[ϵ,σ ]))) Lemma 36
−→ prompt m w ′ (g ((λf . f w ′1◁ pure v ′) (performop[ϵ,σ ]))) (◁)
−→ prompt m w ′ (g (performop[ϵ,σ ] w ′1◁ pure v ′ )) reduces
−→ prompt m w ′ (g (performop[ϵ,σ ] w ′1v ′ )) (◁)
−→ prompt m w ′ (g (let (m, h) = w ′1.l in perform
yield m (λw k. (λf0. f0 w k) ◁ (h.op) w v ′) ))(w ′
1.l = (m, h)) Theorem 5
−→ prompt m w ′ (g (yield m (λw k. (λf0. f0 w k) ◁ (h.op) w v ′) ))−→ prompt m w ′ (g (yield m (λw k. (λf0. f0 w k) ◁ f ′ w v ′) ))let f ′′ = (λw k. (λf0. f0 w k) ◁ f ′ w v ′)−→ prompt m w′ (g (yield m f ′′ id)) yield(g is of form r) Lemma 37
(op ̸∈ bop(E)) given
(op→ f ) ∈ h given
(h ̸∈ bh(E)) otherwise op ∈ bop(E)(handlewm h · E · perform op σ w1 v is m-mapping) Lemma 32
(m ̸∈ ⌈E⌉m ) otherwise h ∈ bh(E)(m ̸∈ bm(g)) Lemma 41
7−→∗ prompt m w ′ (yield m f ′′ (g ◦ id)) Lemma 40
= prompt m w′ (yield m f ′′ g) Lemma 39.1
−→ f ′′ w ′ (guard w′ (prompt m w′ ◦ g)) prompt= f ′′ w ′ k′
= (λw k. (λf0. f0 w k) ◁ f ′ w v ′) w ′ k′
−→ (λf0. f0 w ′ k′) ◁ f ′ w ′ v ′ (app)=β (λf0. f0 w ′ ◁ pure k′) ◁ f ′ w ′ v ′
=β (λf0. f0 w ′ ◁ pure k′) ◁ (f ′ w ′ ◁ (pure v ′))=β (λf0. f0 w ′ ◁ pure k′) ◁ ((λf1. f1 w ′ ◁ (pure v ′)) ◁ pure f ′)case (guardw E σ ) w v −→ E[v].
69
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
∅;w;w ′ ⊩ (guardw E σ1) w v : σ2 | ϵ ⇝ (λf . f w ′ ◁ (pure v ′) ) ◁ (pure (guard w ′ g)) given
∅;w;w ′ ⊩ (guardw E σ1) : σ1⇒ϵ σ2 | ϵ ⇝ (pure (guard w ′ g) ) (mapp)∅;w;w ′ ⊩ v : σ1 | ϵ ⇝ (pure v ′ ) above
∅;w;w ′ ⊩ E : σ1→ σ2 | ϵ ⇝ g′ mguard
(λf . f w ′ ◁ (pure v ′) ) ◁ (pure (guard w ′ g))7−→ (λf . f w ′ ◁ (pure v ′) ) (guard w ′ g) (◁)7−→ guard w′ g w′ ◁ (pure v ′) (app)7−→ guard w′ g w′ v ′ (◁)7−→ if (w ′ == w ′) then g (pure v ′) else wrong guard7−→ g (pure v ′) w ′ == w ′
∅;w;w ′ ⊩ E[v] : σ2 | ϵ ⇝ g′ (pure v ′) Lemma 36
□
B.4.6 Translation Soundness.Proof. (Of Theorem 11) Applying Lemma 43 with w = ⟨⟩ and w ′ = ⟨⟨⟩⟩. □
Lemma 43. (Monadic Translation is Sound)1. If Γ;w;w ′ ⊩ e : σ | ϵ ⇝ e′, then ⌊Γ⌋ ⊢F e′ : mon ϵ ⌊σ ⌋.2. If Γ ⊩val v : σ ⇝ v ′, then ⌊Γ⌋ ⊢F v ′ : ⌊σ ⌋.3. If Γ ⊩ops h : σ | l | ϵ ⇝ h′, then h′ : hndl ϵ ⌊σ ⌋ .4. If Γ;w;w ′ ⊩ec E : σ1→ σ2 | ϵ ⇝ e, then ⌊Γ⌋ ⊢F e : mon ϵ ⌊σ1⌋ → mon ϵ ⌊σ2⌋.
Proof. (Of Theorem 43) Part 1 By induction on the translation.
case e = v.Γ;w;w ′ ⊩ v : σ | ϵ ⇝ pure [⌊σ ⌋] v ′ given
Γ ⊩val v : σ | ϵ ⇝ v ′ mval
⌊Γ⌋ ⊢F v ′ : ⌊σ ⌋ Part 2
⌊Γ⌋ ⊢F pure [⌊σ ⌋] v ′ : mon ϵ ⌊σ ⌋ pure, ftapp and fapp
case e = e [σ ].Γ;w;w ′ ⊩ e[σ ] : σ1[α :=σ ] | ϵ ⇝ e′ ▷ (λx . pure (x[⌊σ ⌋])) given
Γ;w;w ′ ⊩ e : ∀α . σ1 | ϵ ⇝ e′ mtapp
⌊Γ⌋ ⊢F e′ : mon ϵ (∀α . ⌊σ1⌋) I.H.
⌊Γ⌋, x : ∀α . ⌊σ1⌋ ⊢ pure (x[⌊σ ⌋]) : mon ϵ ⌊σ1⌋[α :=⌊σ ⌋] pure, ftapp and fapp
⌊Γ⌋, x : ∀α . ⌊σ1⌋ ⊢ pure (x[⌊σ ⌋]) : mon ϵ ⌊σ1[α :=σ ]⌋ Lemma 33
⌊Γ⌋ ⊢F λx . pure (x[⌊σ ⌋]) : (∀α . ⌊σ1⌋) → mon ⌊σ1[α :=σ ]⌋ fabs
⌊Γ⌋ ⊢F e′ ▷ (λx . pure (x[⌊σ ⌋])) : mon ϵ ⌊σ1[α :=σ ]⌋ ▷case e = e1 e2.
70
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
Γ;w;w ′ ⊩ e1 w e2 : σ | ϵ ⇝ e′1▷ (λf . e′
2▷ f w ′) given
Γ;w;w ′ ⊩ e1 : σ2⇒ϵ σ | ϵ ⇝ e′1
mapp
Γ;w;w ′ ⊩ e2 : σ2 | ϵ ⇝ e′2
above
⌊Γ⌋ ⊢F e′1
: mon ϵ (evv ϵ → ⌊σ2⌋ → mon ϵ ⌊σ ⌋) I.H
⌊Γ⌋ ⊢F e′2
: mon ϵ ⌊σ2⌋ I.H
⌊Γ⌋, f : (evv ϵ → ⌊σ2⌋ → mon ϵ ⌊σ ⌋) ⊢F f : evv ϵ → ⌊σ2⌋ → mon ϵ ⌊σ ⌋ fvar
⌊Γ⌋ ⊢F w ′ : evv ϵ given
⌊Γ⌋, f : (evv ϵ → ⌊σ2⌋ → mon ϵ ⌊σ ⌋) ⊢F w ′ : evv ϵ weakening
⌊Γ⌋, f : (evv ϵ → ⌊σ2⌋ → mon ϵ ⌊σ ⌋) ⊢F f w ′ : ⌊σ2⌋ → mon ϵ ⌊σ ⌋ fapp
⌊Γ⌋, f : (evv ϵ → ⌊σ2⌋ → mon ϵ ⌊σ ⌋) ⊢F e′2
: mon ϵ ⌊σ2⌋ weakening
⌊Γ⌋, f : (evv ϵ → ⌊σ2⌋ → mon ϵ ⌊σ ⌋) ⊢F e′2▷ f w ′ : mon ϵ ⌊σ ⌋ ▷
⌊Γ⌋ ⊢F (λf . e′2 ▷ f w ′) : (evv ϵ → ⌊σ2⌋ → mon ⌊σ ⌋) → mon ϵ ⌊σ ⌋ fabs
⌊Γ⌋ ⊢F e′1▷ (λf . e′
2▷ f w ′) : mon ϵ ⌊σ ⌋ ▷
case e = handlewm h e0.
Γ;w;w ′ ⊩ handlewm h e0 : σ | ϵ ⇝ prompt [ϵ, ⌊σ ⌋] m w ′ e′ given
Γ⊩ops h : σ | l | ϵ ⇝ h′ mhandle
Γ; ⟨⟨l : (m, h) | w⟩⟩; ⟨⟨l : (m, h′) | w ′⟩⟩ ⊩ e : σ | ⟨l | ϵ⟩ ⇝ e′ above
⌊Γ⌋ ⊢F h′ : hndl ϵ ⌊σ ⌋ Part 3
⌊Γ⌋ ⊢′F e′ : mon ⟨l | ϵ⟩ σ I.H.
⌊Γ⌋ ⊢F prompt [ϵ, ⌊σ ⌋] m w ′ e′ : mon ϵ σ prompt, ftapp and fapp
Part 2By induction on the translation. case v = x.
Γ ⊩val x : σ ⇝ x given
x :σ ∈ Γ mvar
x : ⌊σ ⌋ ∈ ⌊Γ⌋ follows
⌊Γ⌋ ⊢F x : ⌊σ ⌋ fvar
case v = λϵ z : evv ϵ, x :σ . e.Γ ⊩val λϵ z : evv ϵ, x : σ1.e : σ1⇒ϵ σ2 ⇝ λz x . e′ given
Γ, z : evv ϵ, x :σ1; z; z ⊩ e : σ2 | ϵ ⇝ e′ mabs
⌊Γ⌋, z : evv ϵ, x : ⌊σ1⌋ ⊢F e′ : mon ϵ ⌊σ2⌋ Part 1
⌊Γ⌋ ⊢F λz x . e′ : evv ϵ → ⌊σ1⌋ → mon ϵ ⌊σ2⌋ fabs
case v = Λαk . v0.
Γ ⊩val Λα . v : ∀α . σ ⇝ Λα . v ′ given
Γ ⊩val v : σ ⇝ v ′ mtabs
⌊Γ⌋ ⊢F v ′ : ⌊σ ⌋ I.H.
⌊Γ⌋ ⊢F Λα . v ′ : ∀α . ⌊σ ⌋ ftabs
case v = handlerϵ h.Γ ⊩val handlerϵ h : (()⇒ ⟨l | ϵ⟩ σ )⇒ ϵ σ ⇝ handler l [ϵ, ⌊σ ⌋] h′ given
Γ⊩ops h : σ | l | ϵ ⇝ h′ mhandle
⌊Γ⌋ ⊢F h′ : hndl ϵ ⌊σ ⌋ Part 3
⌊Γ⌋ ⊢F handler l [ϵ, ⌊σ ⌋] h′ : evv ϵ → (evv ⟨l | ϵ⟩ → () → mon ⟨l | ϵ⟩ σ ) → mon ϵ σ handler , ftapp. fappcase v = performϵ op σ .
Γ ⊩val performϵ op σ : σ1[α :=σ ]⇒ ⟨l | ϵ⟩ σ2[α :=σ ] ⇝ performop [⟨l | ϵ⟩, ⌊σ ⌋] given
op : ∀α . σ1→ σ2 ∈ Σ(l) mperform
⌊Γ⌋ ⊢F performop [⟨l | ϵ⟩, ⌊σ ⌋] : evv ⟨l | ϵ⟩ → ⌊σ1⌋[α :=⌊σ ⌋] → mon ⟨l | ϵ⟩ ⌊σ2⌋[α :=⌊σ ⌋] perform, ftapp
⌊Γ⌋ ⊢F performop [⟨l | ϵ⟩, ⌊σ ⌋] : evv ⟨l | ϵ⟩ → ⌊σ1[α :=σ ]⌋ → mon ⟨l | ϵ⟩ ⌊σ2[α :=σ ]⌋ Lemma 33
71
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
case v = guardw E σ .
Γ ⊩val guardw E σ1 : σ1⇒ϵ σ2 ⇝ guard w′ e′ given
Γ;w;w ′ ⊩ec E : σ1→ σ2 | ϵ ⇝ e′ mguard
⌊Γ⌋ ⊢F e′ : mon ϵ σ1→ mon ϵ σ2 Part 4
⌊Γ⌋ ⊢F guard w′ e′ : evv ϵ → ⌊σ1⌋ → mon ϵ ⌊σ2⌋ guard,fappPart 3
Γ ⊩ops {op1→f1, . . ., opn→ fn} : σ | l | ϵ ⇝ op
1→ f ′
1, . . ., opn→ f ′n given
Γ ⊩val fi : ∀α . σ1⇒ ϵ (σ2⇒ϵ σ )⇒ ϵ σ ⇝ fi′ mops
⌊Γ⌋ ⊢F fi′ : ∀α . evv ϵ → ⌊σ1⌋ → mon ϵ (evv ϵ → (evv ϵ → ⌊σ2⌋ → mon ⌊σ ⌋) → mon ⌊σ ⌋) Part 2
⌊Γ⌋ ⊢F fi′ : ∀α . op ⌊σ1⌋ ⌊σ2⌋ ϵ ⌊σ ⌋ op⌊Γ⌋ ⊢F op
1→ f ′
1, . . ., opn→ f ′n : follows
{op1
: ∀α . op ⌊σ1⌋ ⌊σ2⌋ ϵ ⌊σ ⌋, . . ., opn : ∀α . op ⌊σ1⌋ ⌊σ2⌋ ϵ ⌊σ ⌋}
⌊Γ⌋ ⊢F op1→ f ′
1, . . ., opn→ f ′n : hndl ϵ ⌊σ ⌋ follows
Part 4By induction on the translation.
case E = □.Γ;w;w ′ ⊩ec □ : σ → σ | ϵ ⇝ id given
⌊Γ⌋ ⊢F id : ⌊σ ⌋ → ⌊σ ⌋ idcase E = E0 w e.
Γ;w;w ′ ⊩ec E0 w e : σ1→ σ3 | ϵ ⇝ (λf . e′ ▷ f w) • g given
Γ;w;w ′ ⊩ e : σ2 | ϵ ⇝ e′ mon-capp1
Γ;w;w ′ ⊩ec E0 : σ1→ (σ2⇒ ϵ σ3) | ϵ ⇝ g above
⌊Γ⌋ ⊢F e′ : mon ϵ ⌊σ2⌋ Part 1
⌊Γ⌋ ⊢F g : mon ϵ ⌊σ1⌋ → mon ϵ (evv ϵ → ⌊σ2⌋ → mon ϵ ⌊σ3⌋) I.H.
⌊Γ⌋ ⊢F λf . e′ ▷ f w : (evv ϵ → ⌊σ2⌋ → mon ϵ ⌊σ3⌋) → mon ϵ ⌊σ3⌋ fabs, ▷⌊Γ⌋ ⊢F (λf . e′ ▷ f w) • g : mon ⌊σ1⌋ → mon ϵ ⌊σ3⌋ •
case E = E0 [σ ].
Γ;w;w ′ ⊩ec E0 [σ ] : σ1→ σ2 [α :=σ ] | ϵ ⇝ (λx . pure (x[⌊σ ⌋])) • g given
Γ;w;w ′ ⊩ec E0 : σ1→ ∀α . σ2 | ϵ ⇝ g mon-ctapp
⌊Γ⌋ ⊢F g : mon ϵ ⌊σ1⌋ → mon ϵ (∀α . ⌊σ2⌋) I.H.
⌊Γ⌋ ⊢F (λx . pure (x[⌊σ ⌋])) : (∀α . ⌊σ2⌋) → mon ⌊σ2⌋[α :=⌊σ ⌋] fabs, pure⌊Γ⌋ ⊢F (λx . pure (x[⌊σ ⌋])) : (∀α . ⌊σ2⌋) → mon ⌊σ2[α :=σ ]⌋ Lemma 33
⌊Γ⌋ ⊢F (λx . pure (x[⌊σ ⌋])) • g : mon ϵ ⌊σ1⌋ → mon ⌊σ2[α :=σ ]⌋ •
case E = v w E0.
Γ;w;w ′ ⊩ec v w E0 : σ1→ σ3 | ϵ ⇝ (v ′ w) • g given
Γ;w;w ′ ⊩ec E0 : σ1→ σ2 | ϵ ⇝ g mon-capp2
Γ ⊩val v : σ2⇒ ϵ σ3 ⇝ v ′ above
⌊Γ⌋ ⊢F g : mon ϵ ⌊σ1⌋ → mon ϵ ⌊σ2⌋ I.H.
⌊Γ⌋ ⊢F v ′ : evv ϵ → ⌊σ2⌋ → mon ⌊σ3⌋ Part 1
⌊Γ⌋ ⊢F v ′ w : ⌊σ2⌋ → mon ⌊σ3⌋ fapp
⌊Γ⌋ ⊢F (v ′ w) • g : mon ϵ ⌊σ1⌋ → mon ⌊σ3⌋ •
case E = handlewm h E0.
72
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
Γ;w;w ′ ⊩ec handlewm h E0 : σ1→ σ | ϵ ⇝ prompt[ϵ,σ ] m w ◦ g given
Γ ⊩ops h : σ | l | ϵ ⇝ h′ mon-chandle
Γ; ⟨⟨l : (m, h) | w⟩⟩; ⟨⟨l : (m, h′) | w ′⟩⟩ ⊩ec E0 : σ1→ σ | ⟨l | ϵ⟩ ⇝ g above
⌊Γ⌋ ⊢F h′ : hndl ϵ ⌊σ ⌋ Part 3
⌊Γ⌋ ⊢F g : mon ⟨l | ϵ⟩ ⌊σ1⌋ → mon ⟨l | ϵ⟩ ⌊σ ⌋ above
⌊Γ⌋ ⊢F prompt[ϵ,σ ] m w : mon ⟨l | ϵ⟩ ⌊σ ⌋ → mon ϵ ⌊σ ⌋ above
⌊Γ⌋ ⊢F prompt[ϵ,σ ] m w ◦ g : mon ⟨l | ϵ⟩ ⌊σ1⌋ → mon ϵ ⌊σ ⌋ ◦
□
C FURTHER EXTENSIONSThis section elaborates some further results and extensions to System Fϵ .
C.1 DivergenceIt is well-known that System F is strongly normalizing and evaluation does not diverge [Gi-
rard 1986; Girard et al. 1989] It would be nice to extend that property to System Fϵ . Unfortunately,the extension with algebraic effect handlers is subtle and we cannot claim strong normalization
directly. In particular, the following seemingly well-typed program by Bauer and Pretnar [2015]
diverges but has no direct recursion. Assume cow : { moo : () → (() → ⟨cow⟩ ()) } ∈ Σ, and let
h = { moo→ λx .λ ⟨⟩k. k (λ ⟨cow⟩y. perform moo () ()) }, then:
handler⟨⟩ h (λ ⟨cow⟩_. perform moo () ())7−→∗ handle h · perform moo () () (∗)
= handle h ·□ () · perform moo ()7−→ { k = λ ⟨⟩x : () → ⟨cow⟩ (). handle h ·□ () · x }7−→ f () k7−→ k (λ ⟨cow⟩y. (perform moo ()) ())7−→ handle h ·□ () · (λ ⟨cow⟩y. (perform moo ()) ())7−→ handle h ·□ () · perform moo ()= handle h · perform moo () () (∗)
⇑
The reason for the divergence is that we have accidentally introduced a fancy data type with
handlers of the form { opi → fi }. As discussed in Section 5.2, we translate the operation signatures
to handler data types, where a signature:
l : { op : ∀α . σ1→ σ2 }
gets translated into a data-type:
data hndl µ r = hndl { op : ∀α . op σ1 σ2 µ r }where operations op are a type alias defined as:
alias op α β µ r � evv µ → α → mon (evv µ → (evv µ → β → mon µ r) → mon µ r)
For the encoding of this data type in Fv we can use the standard technique in terms of universal
quantification – as remarked by Wadler [1990]: "Thus, it is safe to extend the polymorphic lambdacalculus by adding least fixpoint types with type variables in positive position. Indeed, no extension isrequired: such types already exist in the language! If F X represents a type containing X in positiveposition only, then least fixpoints may be defined in terms of universal quantification", e.g. as:
lfix α . F α = ∀α . (F α → α) → α
Now we can see where the divergence comes from in our example: the resulting data type hndcow
cannot be encoded in System F (and Fv) as it occurs in a negative position itself!
73
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
Expressions e ::= . . .
| subϵ e effect subsumption
Evaluation Context F ::= . . . | subϵ FE ::= . . . | subϵ E
Operational Rules . . .
subϵ v −→ v
Γ ;w ′ ⊢ e : σ | ϵ ′ ⇝ e′ ϵ ′ ⊑ ϵ | w ⇝ w ′
Γ ;w ⊢ subϵ′
e : σ | ϵ ⇝ subϵ′
e′[sub]
Γ;w ′0;w ′
1⊩ e : σ | ϵ ′ ⇝ e′ ϵ ′ ⊑ ϵ | w1 ⇝ w ′
1
Γ;w0 ;w1 ⊩ subϵ′
e : σ | ϵ ⇝ cast[ϵ, ϵ ′, ⌊σ ⌋] e′[esub]
ϵ ⊑ ϵ | w ⇝ w[sub-refl]
⟨⟩ ⊑ ϵ | w ⇝ ⟨⟨⟩⟩[sub-total]
ϵ ′ ⊑ ϵ | dell w ⇝ w ′
⟨l | ϵ ′⟩ ⊑ ⟨l | ϵ⟩ | w ⇝ ⟨⟨l :w.l | w ′⟩⟩[sub-head]
⟨l′ | ϵ ′⟩ ⊑ ϵ | dell w ⇝ w ′ l , l′
⟨l′ | ϵ ′⟩ ⊑ ⟨l | ϵ⟩ | w ⇝ w ′[sub-forget]
cast : ∀µ µ ′ α . mon µ ′ α → mon µ αcast (pure x) = pure xcast (yield m f cont)= yield m f (cast • cont)
Fig. 14. Effect Subsumption
The operation result parameter β in the op alias occurs in a negative position, and if it is instanti-
atedwith a function itself, like () → ⟨cow⟩ (), themonadic translation has type evv ⟨cow⟩ → () → mon ()where the evidence is now a single element vectorwith one element of type∃µ r . (marker µ r × hndcow µ r),i.e. the evidence contains the the handler type itself, hndcow , recursively in a negative position. As a
consequence, it cannot be encoded using the standard techniques to System F [Wadler 1990] without
breaking strong normalization. In practice, compilers can easily verify if an effect type l occursnegatively in any operation signature to check if effects can be used to encode non-termination.
We can use this too to guarantee termination on well-typed System Fϵ terms as long as we require
that there are no negative occurrences of l in any signature l : { opi : σi → σ ′i }.
C.2 Effect SubsumptionFigure 14 defines effect subsumption in System Fϵ together with typing and translation rules. Note
that subsumption is quite different from subtyping as it is syntactical over terms and does not
change the equality relation between types. The subsumption relation ϵ ′ ⊑ ϵ | w ⇝ w ′ states that
74
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
Effect Handlers, Evidently ICFP ’20, August 23, 2020, Jersey City, New Jersey, US
ϵ ′ is a sub-effect of ϵ , and that evidence w, of type evv ϵ , can be run-time translated into evidence
w ′ of type evv ϵ ′. The dell operation is defined as:
dell : ∀µ . evv ⟨l | µ⟩ → evv µdell ⟨⟨ ⟩⟩ = ⟨⟨ ⟩⟩
dell ⟨⟨l : ev, w⟩⟩ = wdell ⟨⟨l′ : ev, w⟩⟩ = ⟨⟨l′ : ev, dell w⟩⟩ iff l , l′
At runtime sub is translated to the cast function as it has no runtime effect except for changing the
effect type of the monad. All evidence is already in the right form due to the sub-effect relation.
Using subsumption we can derive the open and close type rules introduced by Leijen [2017c]:
Γ ⊢ e : σ1→ ⟨l1, . . ., ln⟩ σ2 | ϵ
Γ ⊢ openϵ′
e : σ1→ ⟨l1, . . ., ln | ϵ ′⟩ σ2 | ϵ[open]
Γ ⊢ e : ∀µ . σ1→ ⟨l1, . . ., ln | µ⟩ σ2 | ϵ
Γ ⊢ close e : σ1→ ⟨l1, . . ., ln⟩ σ2 | ϵ[close]
where we can derive each conclusion as:
openϵ e � λ ⟨l1, ..., ln |ϵ ⟩x :σ1. sub⟨l1, ..., ln⟩ (e x)close e � λ ⟨l1, ..., ln⟩x :σ1. e[⟨⟩] x
The subsumption rule can be used in practice to give many functions a closed effect type (using the
open rule at instantiation) which in turn allows more operations to use a constant offset to index
the handler in the evidence.
C.3 Effect MaskingFigure 15 defines the rules for masking [Convent et al. 2020]. This is also called inject [Leijen 2016],
or lift [Biernacki et al. 2017] in the literature. It is an essential operation for orthogonal composition
of effect handlers as it allows one to skip the innermost handler. For example, we may execute an
action f together with another internal action g where we only want to handle exceptions for gbut not the ones raised in f . With mask we can write this as:
handler hexn (λ_. g (); maskexn (f ()))Even though the operational rule has no effect, we redefine the bound operations to reflect that
mask causes the innermost handler to be skipped. There are various ways to do this, Leijen [2016]
uses a special context definition while Biernacki et al. [2017] use an n-free definition. Here wesimply redefine bop in terms of mbop which uses a multi-map where every operation initially
maps to zero. The handle frame increments the count for bound operations whilemask decrements
them, effectively skipping the next handler in the handle operational rule.
As we can see in the mask rule, masking simply removes the top evidence for the effect l fromthe evidence vector. If f itself raises an exception, the outer evidence will now be used. Therefore,
once we do a monadic translation, the evidence is already transformed and, just like subsumption,
the mask operation itself has no further runtime effect anymore (and can use the cast function as
well).
75
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
ICFP ’20, August 23, 2020, Jersey City, New Jersey, USNingning Xie, Jonathan Immanuel Brachthäuser, Daniel Hillerström, Philipp Schuster, and Daan Leijen
Expressions e ::= . . .
| maskl e effect masking
Evaluation Context F ::= . . . | maskl FE ::= . . . | maskl E
Operational Rules . . .
maskl v −→ v
Γ ; dell w ⊢ e : σ | ϵ ⇝ e′
Γ ;w ⊢ maskl e : σ | ⟨l | ϵ⟩ ⇝ maskl e′[mask]
Γ; dell w ; dell w ′ ⊩ e : σ | ϵ ⇝ e′
Γ;w ;w ′ ⊩ maskl e : σ | ⟨l | ϵ⟩ ⇝ cast[⟨l | ϵ⟩, ϵ, ⌊σ ⌋] e′[emask]
bop(E) = { op | (op : i) ∈ mbop(E), i ⩾ 1 }
mbop(□) = {{ op : 0 | op ∈ Σ}}mbop(E e) = mbop(E)mbop(v E) = mbop(E)mbop(handle h E) = mbop(E) + {{ op : 1 | (op→ f ) ∈ h }}mbop(maskl E) = mbop(E) + {{ op : −1 | (op : σ1→ σ2) ∈ Σ(l) }}
Fig. 15. Effect Masking
76