20 research outputs found
Foundations for programming and implementing effect handlers
First-class control operators provide programmers with an expressive and efficient
means for manipulating control through reification of the current control state as a first-class object, enabling programmers to implement their own computational effects and
control idioms as shareable libraries. Effect handlers provide a particularly structured
approach to programming with first-class control by naming control reifying operations
and separating from their handling.
This thesis is composed of three strands of work in which I develop operational
foundations for programming and implementing effect handlers as well as exploring
the expressive power of effect handlers.
The first strand develops a fine-grain call-by-value core calculus of a statically
typed programming language with a structural notion of effect types, as opposed to the
nominal notion of effect types that dominates the literature. With the structural approach,
effects need not be declared before use. The usual safety properties of statically typed
programming are retained by making crucial use of row polymorphism to build and
track effect signatures. The calculus features three forms of handlers: deep, shallow,
and parameterised. They each offer a different approach to manipulate the control state
of programs. Traditional deep handlers are defined by folds over computation trees,
and are the original con-struct proposed by Plotkin and Pretnar. Shallow handlers are
defined by case splits (rather than folds) over computation trees. Parameterised handlers
are deep handlers extended with a state value that is threaded through the folds over
computation trees. To demonstrate the usefulness of effects and handlers as a practical
programming abstraction I implement the essence of a small UNIX-style operating
system complete with multi-user environment, time-sharing, and file I/O.
The second strand studies continuation passing style (CPS) and abstract machine
semantics, which are foundational techniques that admit a unified basis for implementing deep, shallow, and parameterised effect handlers in the same environment. The
CPS translation is obtained through a series of refinements of a basic first-order CPS
translation for a fine-grain call-by-value language into an untyped language. Each refinement moves toward a more intensional representation of continuations eventually
arriving at the notion of generalised continuation, which admit simultaneous support for
deep, shallow, and parameterised handlers. The initial refinement adds support for deep
handlers by representing stacks of continuations and handlers as a curried sequence of
arguments. The image of the resulting translation is not properly tail-recursive, meaning some function application terms do not appear in tail position. To rectify this the
CPS translation is refined once more to obtain an uncurried representation of stacks
of continuations and handlers. Finally, the translation is made higher-order in order to
contract administrative redexes at translation time. The generalised continuation representation is used to construct an abstract machine that provide simultaneous support for
deep, shallow, and parameterised effect handlers. kinds of effect handlers.
The third strand explores the expressiveness of effect handlers. First, I show that
deep, shallow, and parameterised notions of handlers are interdefinable by way of typed
macro-expressiveness, which provides a syntactic notion of expressiveness that affirms
the existence of encodings between handlers, but it provides no information about the
computational content of the encodings. Second, using the semantic notion of expressiveness I show that for a class of programs a programming language with first-class
control (e.g. effect handlers) admits asymptotically faster implementations than possible in a language without first-class control
Effect handlers via generalised continuations
Plotkin and Pretnar's effect handlers offer a versatile abstraction for modular programming with user-defined effects. This paper focuses on foundations for implementing effect handlers, for the three different kinds of effect handlers that have been proposed in the literature: deep, shallow, and parameterised. Traditional deep handlers are defined by folds over computation trees, and are the original construct proposed by Plotkin and Pretnar. Shallow handlers are defined by case splits (rather than folds) over computation trees. Parameterised handlers are deep handlers extended with a state value that is threaded through the folds over computation trees. We formulate the extensions both directly and via encodings in terms of deep handlers, and illustrate how the direct implementations avoid the generation of unnecessary closures. We give two distinct foundational implementations of all the kinds of handlers we consider: a continuation passing style (CPS) transformation and a CEK-style abstract machine. In both cases, the key ingredient is a generalisation of the notion of continuation to accommodate stacks of effect handlers. We obtain our CPS translation through a series of refinements as follows. We begin with a first-order CPS translation into untyped lambda calculus which manages a stack of continuations and handlers as a curried sequence of arguments. We then refine the initial CPS translation by uncurrying it to yield a properly tail-recursive translation, and then moving towards more and more intensional representations of continuations in order to support different kinds of effect handlers. Finally, we make the translation higher-order in order to contract administrative redexes at translation time. Our abstract machine design then uses the same generalised continuation representation as the CPS translation. We have implemented both the abstract machine and the CPS transformation (plus extensions) as backends for the Links web programming language
Continuation Passing Style for Effect Handlers
We present Continuation Passing Style (CPS) translations for Plotkin and Pretnar's effect handlers with Hillerström and Lindley's row-typed fine-grain call-by-value calculus of effect handlers as the source language. CPS translations of handlers are interesting theoretically, to explain the semantics of handlers, and also offer a practical implementation technique that does not require special support in the target language's runtime. We begin with a first-order CPS translation into untyped lambda calculus which manages a stack of continuations and handlers as a curried sequence of arguments. We then refine the initial CPS translation first by uncurrying it to yield a properly tail-recursive translation and second by making it higher-order in order to contract administrative redexes at translation time. We prove that the higher-order CPS translation simulates effect handler reduction. We have implemented the higher-order CPS translation as a JavaScript backend for the Links programming language
Soundly Handling Linearity
We propose a novel approach to soundly combining linear types with effect
handlers. Linear type systems statically ensure that resources such as file
handles are used exactly once. Effect handlers provide a modular programming
abstraction for implementing features ranging from exceptions to concurrency.
Whereas linear type systems bake in the assumption that continuations are
invoked exactly once, effect handlers allow continuations to be discarded or
invoked more than once. This mismatch leads to soundness bugs in existing
systems such as the programming language Links, which combines linearity (for
session types) with effect handlers. We introduce control flow linearity as a
means to ensure that continuations are used in accordance with the linearity of
any resources they capture, ruling out such soundness bugs.
We formalise control flow linearity in a System F-style core calculus Feffpop
equipped with linear types, effect types, and effect handlers. We define a
linearity-aware semantics to formally prove that Feffpop preserves the
integrity of linear values in the sense that no linear value is discarded or
duplicated. In order to show that control flow linearity can be made practical,
we adapt Links based on the design of Feffpop, in doing so fixing a
long-standing soundness bug.
Finally, to better expose the potential of control flow linearity, we define
an ML-style core calculus Qeffpop, based on qualified types, which requires no
programmer provided annotations, and instead relies entirely on type inference
to infer control flow linearity. Both linearity and effects are captured by
qualified types. Qeffpop overcomes a number of practical limitations of
Feffpop, supporting abstraction over linearity, linearity dependencies between
type variables, and a much more fine-grained notion of control flow linearity.Comment: 51 pages, accepted for POPL 202
Effects for Efficiency: Asymptotic Speedup with First-Class Control
We study the fundamental efficiency of delimited control. Specifically, we
show that effect handlers enable an asymptotic improvement in runtime
complexity for a certain class of functions. We consider the generic count
problem using a pure PCF-like base language and its extension with
effect handlers . We show that admits an asymptotically
more efficient implementation of generic count than any
implementation. We also show that this efficiency gap remains when
is extended with mutable state. To our knowledge this result is the first of
its kind for control operators
Structural Subtyping as Parametric Polymorphism
Structural subtyping and parametric polymorphism provide similar flexibility
and reusability to programmers. For example, both features enable the
programmer to provide a wider record as an argument to a function that expects
a narrower one. However, the means by which they do so differs substantially,
and the precise details of the relationship between them exists, at best, as
folklore in literature.
In this paper, we systematically study the relative expressive power of
structural subtyping and parametric polymorphism. We focus our investigation on
establishing the extent to which parametric polymorphism, in the form of row
and presence polymorphism, can encode structural subtyping for variant and
record types. We base our study on various Church-style -calculi
extended with records and variants, different forms of structural subtyping,
and row and presence polymorphism.
We characterise expressiveness by exhibiting compositional translations
between calculi. For each translation we prove a type preservation and
operational correspondence result. We also prove a number of non-existence
results. By imposing restrictions on both source and target types, we reveal
further subtleties in the expressiveness landscape, the restrictions enabling
otherwise impossible translations to be defined. More specifically, we prove
that full subtyping cannot be encoded via polymorphism, but we show that
several restricted forms of subtyping can be encoded via particular forms of
polymorphism.Comment: 47 pages, accepted by OOPSLA 202
Continuing WebAssembly with Effect Handlers
WebAssembly (Wasm) is a low-level portable code format offering near native performance. It is intended as a compilation target for a wide variety of source languages. However, Wasm provides no direct support for non-local control flow features such as async/await, generators/iterators, lightweight threads, first-class continuations, etc. This means that compilers for source languages with such features must ceremoniously transform whole source programs in order to target Wasm. We present WasmFX an extension to Wasm which provides a universal target for non-local control features via effect handlers, enabling compilers to translate such features directly into Wasm. Our extension is minimal and only adds three main instructions for creating, suspending, and resuming continuations. Moreover, our primitive instructions are type-safe providing typed continuations which are well-aligned with the design principles of Wasm whose stacks are typed. We present a formal specification of WasmFX and show that the extension is sound. We have implemented WasmFX as an extension to the Wasm reference interpreter and also built a prototype WasmFX extension for Wasmtime, a production-grade Wasm engine, piggybacking on Wasmtime's existing fibers API. The preliminary performance results for our prototype are encouraging, and we outline future plans to realise a native implementation
Typed concurrent functional programming with channels, actors and sessions
The age of writing single-threaded applications is over. To develop scalable applications, developers
must make use of concurrency and parallelism. Nonetheless, introducing concurrency
and parallelism is difficult: naïvely implemented, concurrent code is prone to issues such as
race conditions and deadlocks. Moving to the distributed setting introduces yet more issues,
in particular the possibility of failure.
To cope with many of the problems of concurrent programming, language designers have
proposed a class of programming languages known as communication-centric programming
languages, which provide lightweight processes which do not share memory, but instead communicate
using explicit message passing. The focus of this thesis is on typed communication-centric
functional programming languages, using type systems to provide static guarantees
about the runtime behaviour of concurrent programs. We investigate two strands of work:
the relationship between typed channel- and actor-based languages, and the integration of
asynchrony, exception handling, and session types in a functional programming language.
In the first strand, we investigate two particular subclasses of communication-centric
languages: channel-based languages such as Go, and languages based on the actor model, such
as Erlang. We distil the essence of the languages into two concurrent λ-calculi: λch for simply-typed
channels, and lact for simply-typed actors, and provide type- and semantics-preserving
translations between them. In doing so, we clear up confusion between the two models,
give theoretical foundations for recent implementations of type-parameterised actors, and
also provide a theoretical grounding for frameworks which emulate actors in channel-based
languages. Furthermore, by extending the core calculi, we note that actor synchronisation
drastically simplifies the translation from channels into actors, and show that Erlang’s selective
receive mechanism can be implemented without specialised constructs.
In the second strand, we integrate session types, asynchrony, and exception handling
in a functional programming language. Session types are a behavioural type system for
communication channel endpoints, allowing conformance to protocols to be checked statically.
We provide the first integration of exception handling and asynchronous session types in a core
functional language, Exceptional GV, and prove that it satisfies preservation, global progress,
and that it is confluent and terminating. We demonstrate the practical applicability of the
approach by extending the Links tierless web programming language with exception handling,
in turn providing the first implementation of exception handling in the presence of session
types in a functional language. As a result, we show the first application of session types to
web programming, providing examples including a two-factor authentication workflow and a
chat application