---
title: One-Shot Effect Handlers
url: https://www.emergentmind.com/topics/one-shot-effect-handlers
type: topic
---

# One-Shot Effect Handlers

Searching arXiv for recent and foundational papers on one-shot effect handlers and closely related work.
One-shot effect handlers are a restricted variant of algebraic effect handlers in which each captured continuation can be resumed at most once [2509.11901]. They belong to the broader algebraic view in which effects are viewed as algebraic operations and effect handlers as homomorphisms from free algebras [1203.1539]. Across the recent literature, one-shotness appears in several forms: as a dynamic property of continuations that trap on reuse, as a static control-flow discipline derived from linear types, and as an affine restriction that supports modular reasoning for higher-order and bidirectional control. The topic therefore sits at the intersection of effect semantics, type systems, runtime design, and expressiveness theory [2308.08347][2307.09383].

## 1. Algebraic handlers and the contrast with reusable resumptions

In the standard algebraic-effects setting, a handler gives meaning to operations by handling their occurrences in computations and receiving the continuation at the point of effect invocation. In Eff, computations are interpreted as mapping to a domain \((V + O)_{\bot}\), where \(O\) contains triples of instance, operation, argument, and continuation; a handler processes either a value or an operation occurrence, and unhandled operations are repackaged and propagated upward [1203.1539]. This makes continuations explicit semantic objects and fixes the point of comparison for one-shot restrictions.

Eff also provides the canonical reusable baseline. Its handlers are by default resumable: the continuation `k` passed to an operation clause can be called zero, once, or multiple times, as in choice, probabilistic choice, breadth-first search, and delimited-control encodings [1203.1539]. There is no built-in distinction or enforcement of one-shot versus multi-shot continuations in the core design. Exception handling is a special case only because `raise : 'a -> empty` makes resumption impossible by type [1203.1539].

A similar contrast appears in calculi outside conventional programming-language implementation. The calculus for natural-language semantics based on algebraic effects and handlers proves subject reduction, confluence, and strong normalization for well-typed terms, but it does not explicitly discuss one-shot handlers; its handlers are reusable and not subject to linearity or resource-sensitive constraints [1606.06125]. This establishes that one-shot effect handlers are not part of the original algebraic-handler core, but a later specialization motivated by safety, efficiency, or both.

## 2. What “one-shot” means, and how it differs from linear control-flow

The most direct definition in the recent literature is operational: one-shot effect handlers are a restricted variant of general algebraic effect handlers in which each captured continuation can be resumed at most once [2509.11901]. In WasmFX, this restriction is enforced dynamically: continuations are one-shot, after resumption a continuation cannot be reused, and attempting to do so causes a trap [2308.08347]. The reduction rule shown for a dead continuation makes the operational meaning explicit:
$$
s[k = \dagger]; (\text{ref. }k)\;(\mathrm{resume}_f~h^*) \to s[k = \dagger]; \text{trap}
$$

A distinct but closely related notion appears in work on linear types and handlers. There, the central issue is that linear type systems assume continuations are invoked exactly once, whereas ordinary effect handlers allow continuations to be discarded or invoked more than once [2307.09383]. The proposed answer is control-flow linearity, which tracks, for each operation, how many times the continuation captured at the operation point may be invoked. In this setting, linear control-flow means the continuation must be invoked exactly once, while unlimited control-flow means it may be invoked multiple times; one-shot effect handlers become a special case obtained by assigning linear control-flow linearity to the relevant operations [2307.09383].

The distinction matters technically. “At most once” is an affine constraint, while “exactly once” is linear. The literature represented here uses both vocabularies because different systems optimize for different guarantees. WasmFX uses one-shot continuations to simplify implementation and memory management [2308.08347]. Feffpop and Qeffpop use a stronger linear discipline to protect captured linear resources and then observe that one-shot handler behavior is expressible within that framework [2307.09383].

## 3. Static enforcement: control-flow linearity, polymorphism, and separation of concerns

The most fully developed static account is the control-flow-linearity approach of Feffpop and Qeffpop. Feffpop is a System F-style core calculus with linear types, effect types, and effect handlers; it tracks linearity both at the value-type level and at the effect or operation level [2307.09383]. Operation signatures have the form \(A^{Y} B\), where \(Y\) records the control-flow linearity of the captured continuation. If \(\ell : A^{Y} B\), then the handler’s resumption variable has type \(B \to^{Y} D\); when \(Y = \mathsf{Lin}\), the resumption is a linear function and must be called exactly once [2307.09383]. The sequencing rule similarly reflects the control-flow linearity of the continuation, and the system exploits a duality in subkinding: for values, \( \mathsf{Unl} \leq \mathsf{Lin} \), whereas for effects and contexts, \( \mathsf{Lin} \leq \mathsf{Unl} \) [2307.09383].

This discipline is motivated by a concrete soundness problem. Links combined session-typed channels with multi-shot effect handlers and admitted a program that typechecked but at runtime attempted to use a linear resource more than once due to double invocation of a multi-shot continuation [2307.09383]. The Feffpop design was adapted to Links by introducing control-flow linearity kinds (`Lin`, `Any`), separate arrows for linear (`=@`) and unlimited (`=>`) operations, and syntax for linear contexts such as `lindo`; the adaptation fixed the long-standing bug and was backward compatible [2307.09383]. The paper also gives a linearity-aware operational semantics and proves a Linearity Safety Theorem: any well-typed Feffpop program will never duplicate or discard a linear value during evaluation, including in the presence of multi-shot handlers [2307.09383].

Qeffpop pushes the same idea toward practical inference. It is an ML-style calculus with qualified types in which both linearity and effects are captured by predicates, programmer annotations are unnecessary, and type inference infers control-flow linearity [2307.09383]. The example type
$$
\mathrm{verboseId} : \forall\,\alpha\,\mu\,\phi\,\phi'.\, (\alpha \leq \phi) \Rightarrow \alpha \to^{\phi'} \alpha \ \{Print : \phi ; \mu\}
$$
illustrates how a linearity variable can encode whether an operation’s continuation is linear. The system also supports abstraction over linearity, linearity dependencies between type variables, and qualified row polymorphism [2307.09383]. A plausible implication is that one-shot effect handlers can be treated as inferred control-flow properties rather than as a separate programmer-visible feature.

Other static accounts reach one-shot behavior from different directions. In the calculus for polymorphic algebraic effects and handlers, unrestricted let-polymorphism is retained by restricting handlers rather than let-bound expressions: resumptions must be non-interfering, and each `resume` is typechecked at a fresh instantiation of the operation’s type parameters [1811.07332]. The paper explicitly connects this to a one-shot perspective, stating that resumptions must behave as if each were used in isolation. In the calculus for higher-order effects, the separation-of-concerns theorem depends on handlers whose operation clauses call the continuation at most once; the paper describes this as an affine or one-shot discipline and contrasts it with non-determinism handlers that resume a continuation more than once [2203.03288].

## 4. Runtime mechanisms and compilation targets

A contrasting line of work treats one-shotness as a runtime property and exploits it for low-level implementation. WasmFX extends WebAssembly with a minimal instruction set for creating, suspending, and resuming continuations: `cont.new`, `suspend`, and `resume` [2308.08347]. The extension provides typed continuations aligned with Wasm’s typed stacks, formalizes the new constructs, and proves type preservation and progress. Operationally, `cont.new` allocates a continuation, `suspend` captures the current continuation up to the nearest applicable handler and transfers control to the handler, and `resume` marks the continuation as dead, installs handler clauses, and restarts the continuation in its stack context [2308.08347].

The one-shot choice is central to the runtime architecture. Used continuations cause a trap; references to used continuations are nulled out or trapped in the prototype; and the affine discipline is presented as enabling stack reuse, reference counting, and avoidance of cycles in memory [2308.08347]. WasmFX is implemented both in the Wasm reference interpreter and as a Wasmtime prototype piggybacking on Wasmtime’s existing fibers API, with continuations mapped to fibers and stack switching implemented natively on x86_64 [2308.08347]. The compilation payoff is direct style: advanced control features such as async/await, generators, coroutines, lightweight threads, and actors can be translated into WasmFX without whole-program CPS or state-machine transformations [2308.08347].

The available systems therefore occupy different points in the design space:

| System | One-shot status | Mechanism |
|---|---|---|
| Eff | Not built in; exceptions only by `empty` result type | Multi-shot resumptions by default |
| Feffpop / Qeffpop | Expressible and statically guaranteed | Control-flow linearity and qualified types |
| WasmFX | Built in for continuations | `resume` consumes continuation; reuse traps |

The reported performance data for WasmFX make the engineering trade-off concrete. In a microbenchmark simulating 10,000 coroutines concurrently, the WasmFX binary is 0.8 KB, compared with 9.2 KB for Asyncify, while runtime is approximately \(3\times\) slower: 2700ms for WasmFX, 700ms for Asyncify, and 140ms for a hand-written state machine; memory usage is similar to Asyncify [2308.08347]. The paper attributes much of the overhead to fiber switches and crossing the Wasm–host boundary.

## 5. Expressive power, coroutines, and bidirectional control

The theoretical status of one-shot effect handlers has recently been clarified in macro-expressiveness terms. Using Felleisen’s notion of macro-expressiveness, one-shot effect handlers and one-shot delimited-control operators can be macro-expressed by asymmetric coroutines, but asymmetric coroutines cannot be macro-expressed by one-shot effect handlers or one-shot delimited control [2509.11901]. The paper explicitly revises a previous informal argument and attributes the gap to the structure of control transfer: coroutines support symmetric control transfer patterns that are not stack-based in the way handlers and delimited-control operators are [2509.11901].

This result places one-shot effect handlers below asymmetric coroutines in the hierarchy induced by macro-expressibility. It does not make one-shot handlers unimportant; rather, it locates them precisely. They remain adequate for many language features that are naturally stack-delimited, and they are attractive when efficiency or static reasoning dominates. But the impossibility result for macro-expressing asymmetric coroutines means that one-shot handlers are not a universal replacement for all one-shot control abstractions [2509.11901].

A related extension of the handler idea appears in bidirectional algebraic effects. There, handlers may raise further effects that transfer control back to the site where the initiating effect was raised, and handlers may use themselves to handle their own effects [2010.09073]. The paper distinguishes this from traditional unidirectional handlers and notes that the common case includes tail-resumptive or one-shot bidirectional handlers, where after `resume` the handler does nothing further. These cases can be compiled efficiently, and preliminary experiments report native bidirectional handlers as 2.1× faster than callback-based encodings in the `u$` C++ extension [2010.09073]. The result suggests that one-shot usage patterns remain central even when the control structure is more powerful than ordinary handler resumption.

## 6. Higher-order effects, applications, and limits of the one-shot view

One-shot disciplines become particularly significant when handlers are used for effects beyond first-order algebraic operations. The higher-order-effects calculus \(\lambda^{hop}\) introduces suspensions, latent effects, and handlers whose continuations consume suspensions rather than plain values, precisely so that operations with computation parameters such as `catch` can be handled directly [2203.03288]. The paper’s central meta-theoretic result on separation of concerns depends on an affine restriction: a handler has separate concerns when its return clause behaves appropriately and each operation clause calls the continuation at most once [2203.03288]. The non-determinism handler that invokes the continuation twice is the standard counterexample. In this setting, one-shotness is not merely an optimization device; it is a sufficient condition for handler commutation properties.

At the same time, several important effect-handler applications remain explicitly multi-shot. Eff uses multi-shot resumptions to model backtracking, breadth-first search, probabilistic choice, cooperative multi-threading, and forms of delimited continuations [1203.1539]. The natural-language-semantics calculus likewise relies on reusable handlers as modular interpreters for deixis, quantification, and conventional implicature, and it neither implements nor discusses one-shot restrictions [1606.06125]. These cases show that the motivation for one-shot effect handlers is selective rather than universal: it arises when continuation reuse is semantically unnecessary or operationally problematic, not whenever handlers are used.

The present research landscape therefore supports a differentiated view. One-shot effect handlers are valuable where linear resources must not be duplicated, where direct-style compilation benefits from affine continuations, or where modularity theorems depend on at-most-once resumption [2307.09383][2308.08347][2203.03288]. Multi-shot handlers remain essential where continuation duplication is the intended semantics, as in nondeterminism and search [1203.1539]. A plausible implication is that the most robust language designs will continue to distinguish, rather than collapse, these regimes: some already mix one-shot and multi-shot operations in the same program with static guarantees [2307.09383].

Source: https://www.emergentmind.com/topics/one-shot-effect-handlers