publications

Process calculi based in logic, such as πDILL and CP, provide a foundation for deadlock-free
concurrent programming, but exclude non- determinism and races. HCP is a reformulation of CP
which addresses a fundamental shortcoming: the fundamental operator for parallel com- position
from the π-calculus does not correspond to any rule of linear logic, and therefore not to any
term construct in CP. We introduce HCP–ND , which extends HCP with a
novel account of non- determinism. Our approach draws on bounded linear logic to provide a
strongly-typed account of standard process calculus expressions of non-determinism. We show
that our extension is expressive enough to capture many uses of non-determinism in untyped
calculi, such as non- deterministic choice, while preserving HCP's meta-theoretic properties,
including deadlock freedom.

We present a novel typed language for extensible data types, generalizing and abstracting
existing systems of row types and row polymorphism. Extensible data types are a powerful
addition to traditional functional programming languages, capturing ideas from OOP-like record
extension and polymorphism to modular compositional interpreters. We introduce row theories, a
monoidal generalization of row types, giving a general account of record concatenation and
projection (dually, variant injection and branching). We realize them via qualified types,
abstracting the interpretation of records and variants over different row theories. Our
approach naturally types terms untypable in other systems of extensible data types, while
maintaining strong metatheoretic properties, such as coherence and principal types. Evidence
for type qualifiers has computational content, determining the implementation of record and
variant operations; we demonstrate this in giving a modular translation from our calculus,
instantiated with various row theories, to polymorphic λ-calculus.

Session types statically guarantee that communication complies with a protocol. However, most
accounts of session typing do not account for failure, which means they are of limited use in
real applications—especially distributed applications—where failure is pervasive.

We present the first formal integration of asynchronous session types with exception handling
in a functional programming language. We define a core calculus which satisfies preservation
and progress properties, is deadlock free, confluent, and terminating.

We provide the first implementation of session types with exception handling for a
fully-fledged functional programming language, by extending the Links web programming language;
our implementation draws on existing work on effect handlers. We illustrate our approach
through a running example of two-factor authentication, and a larger example of a session-based
chat application where communication occurs over session-typed channels and disconnections are
handled gracefully.

Gradual typing has emerged as the tonic for programmers wanting a mixture of static and dynamic
typing, hoping to achieve the best of both. Sound gradual typing is the most potent brew,
providing static type- checking and dynamic assertions. Contracts provide a lightweight form of
gradual typing as they do not provide static checking but can be implemented as a library,
rather than demanding language level support.

Intersection and union types are well suited to dynamic languages: intersection encodes
overloaded functions; union encodes uncertain data arising from branching code. We extend the
untyped lambda calculus with contracts for monitoring higher-order intersection and union
types, giving a uniform treatment to both. Each operator requires a single reduction rule that
does not depend on the constituent types, or the context of the operator, unlike existing work.

We present a new method for defining contract satisfaction based on blame behaviour. A value
positively satisfies a type if, when monitored against that type in any context, never elicits
positive blame. A continuation negatively satisfies a type if, when monitored against that type
using any value, never elicits negative blame.

We supplement our definition of satisfaction with a serious of monitoring properties that
satisfying values and continuations should have. Each type has a positive property for values
and a negative property for continuations, ensuring that contracts reflect the types they
represent.

We present an approach to support partiality in type-level computation without compromising
expressiveness or type safety. Existing frameworks for type-level computation either require
totality or implicitly assume it. For example, type families in Haskell provide a powerful,
modular means of defining type-level computation. However, their current design implicitly
assumes that type families are total, introducing nonsensical types and significantly
complicating the metatheory of type families and their extensions. We propose an alternative
design, using qualified types to pair type-level computations with predicates that capture
their domains. Our approach naturally captures the intuitive partiality of type families,
simplifying their metatheory. As evidence, we present the first complete proof of consistency
for a language with closed type families.

Extended edition available in PDF.
The conference version is available from
the ACM DL, or
in PDF.

TypeScript participates in the recent trend among programming languages to support gradual
typing. The DefinitelyTyped Repository for TypeScript supplies type definitions for over 2000
popular JavaScript libraries. However, there is no guarantee that implementations conform to
their corresponding declarations.

We present a practical evaluation of gradual typing for TypeScript. We have developed a tool,
based on the polymorphic blame calculus, for monitoring JavaScript libraries and TypeScript
clients against the TypeScript definition. We apply our tool, TypeScript TNG, to those
libraries in the DefinitelyTyped Repository which had adequate test code to use. Of the 122
libraries we checked, 59 had cases where either the library or its tests failed to conform to
the declaration.

Gradual typing should satisfy non-interference. Monitoring a program should never change its
behaviour except, to raise a type error should a value not conform to its declared
type. However, our experience also suggests serious technical concerns with the use of the
JavaScript proxy mechanism for enforcing contracts. Of the 122 libraries we checked, 22 had
cases where the library or its tests violated non-interference.

▷▽
J. Garrett Morris. "The Best of Both Worlds: Linear Functional Programming Without Compromise".
In Proceedings of the 21st ACM SIGPLAN International Conference on Functional Programming
(ICFP 2016), Nara, Japan, 2016.

We present a linear functional calculus with both the safety guarantees expressible with linear
types and the rich language of combinators and composition provided by functional programming.
Unlike previous combinations of linear typing and functional programming, we compromise neither
the linear side (for example, our linear values are first-class citizens of the language) nor
the functional side (for example, we do not require duplicate definitions of compositions for
linear and unrestricted functions). To do so, we must generalize abstraction and application
to encompass both linear and unrestricted functions. We capture the typing of the generalized
constructs with a novel use of qualified types. Our system maintains the metatheoretic
properties of the theory of qualified types, including principal types and decidable type
inference. Finally, we give a formal basis for our claims of expressiveness, by showing that
evaluation respects linearity, and that our language is a conservative extension of existing
functional calculi.

The extended edition is available in PDF.
Note that this version fixes several inadvertent omissions and typographical errors, and so
should be preferred to the conference version. The conference version is available from
the ACM DL.

Session types provide static guarantees that concurrent programs respect communication
protocols. We give a novel account of recursive session types in the context of GV, a small
concurrent extension of the linear λ-calculus. We extend GV with recursive types and
catamorphisms, following the initial algebra semantics of recursion, and show that doing so
naturally gives rise to recursive session types. We show that this principled approach to
recursion resolves long-standing problems in the treatment of duality for recursive session
types.

We characterize the expressiveness of GV concurrency by giving a CPS translation to
(non-concurrent) λ-calculus and proving that reduction in GV is simulated by full
reduction in λ-calculus. This shows that GV remains terminating in the presence of
positive recursive types, and that such arguments extend to other extensions of GV, such as
polymorphism or non-linear types, by appeal to normalization results for sequential
λ-calculi. We also show that GV remains deadlock free and deterministic in the presence
of recursive types.

Finally, we extend CP, a session-typed process calculus based on linear logic, with recursive
types, and show that doing so preserves the connection between reduction in GV and cut
elimination in CP.

We present a novel embedding of session-typed concurrency in Haskell.
We extend an existing HOAS embedding of the linear λ-calculus with a set of core
session-typed primitives, using indexed type families to express the constraints of the session
typing discipline.
We give two interpretations of our embedding, one in terms of GHC's built-in concurrency and
another in terms of purely functional continuations.
Our safety guarantees, including deadlock freedom, are assured statically and introduce no
additional runtime overhead.

▷▽
Robert Atkey, Sam Lindley, and J. Garrett Morris. "Conflation Confers Concurrency". In A
List of Successes That Can Change the World: Essays Dedicated to Philip Wadler on the Occasion
of His 60th Birthday. LNCS
9600.

Session types provide a static guarantee that concurrent programs respect communication
protocols. Recent work has explored a correspondence between proof rules and cut reduction in
linear logic and typing and evaluation of process calculi. This paper considers two approaches
to extend logically-founded process calculi. First, we consider extensions of the process
calculus to more closely resemble π-calculus. Second, inspired by denotational models of
process calculi, we consider conflating dual types. Most interestingly, we observe that these
approaches coincide: conflating the multiplicatives (⊗ and ⅋) allows processes to
share multiple channels; conflating the additives (⊕ and &) provides
nondeterminism; and conflating the exponentials (! and ?) yields access points, a
rendezvous mechanism for initiating session typed communication. Access points are
particularly expressive: for example, they are sufficient to encode concurrent state and
general recursion.

Extensible variants improve the modularity and expressiveness of programming languages: they
allow program functionality to be decomposed into independent blocks, and allow seamless
extension of existing code with both new cases of existing data types and new operations over
those data types.

This paper considers three approaches to providing extensible variants in Haskell. Row typing
is a long understood mechanism for typing extensible records and variants, but its adoption
would require extension of Haskell's core type system. Alternatively, we might hope to encode
extensible variants in terms of existing mechanisms, such as type classes. We describe an
encoding of extensible variants using instance chains, a proposed extension of the class
system. Unlike many previous encodings of extensible variants, ours does not require the
definition of a new type class for each function that consumes variants. Finally, we translate
our encoding to use closed type families, an existing feature of GHC. Doing so demonstrates
the interpretation of instances chains and functional dependencies in closed type families.

One concern with encodings like ours is how completely they match the encoded system. We
compare the expressiveness of our encodings with each other and with systems based on row
types. We find that, while equivalent terms are typable in each system, both encodings require
explicit type annotations to resolve ambiguities in typing not present in row type systems, and
the type family implementation retains more constraints in principal types than does the
instance chain implementation. We propose a general mechanism to guide the instantiation of
ambiguous type variables, show that it eliminates the need for type annotations in our
encodings, and discuss conditions under which it preserves coherence.

Paper available from the ACM
DL or in PDF. Sample code available
here.

Session types provide a static guarantee that concurrent programs respect communication
protocols. Recently, Caires, Pfenning, and Toninho, and Wadler, have developed a correspondence
between propositions of linear logic and session typed π-calculus processes.
We relate the cut-elimination semantics of this approach to an operational semantics for
session-typed concurrency in a functional language.
We begin by presenting a variant of Wadler's session-typed core functional language, GV. We
give a small-step operational semantics for GV. We develop a suitable notion of deadlock, based
on existing approaches for capturing deadlock in π-calculus, and show that all well-typed
GV programs are deadlock-free, deterministic, and terminating.
We relate GV to linear logic by giving translations between GV and CP, a process calculus with
a type system and semantics based on classical linear logic. We prove that both directions of
our translation preserve reduction; previous translations from GV to CP, in contrast, failed to
preserve β-reduction.
Furthermore, to demonstrate the modularity of our approach, we define two extensions of GV
which preserve deadlock-freedom, determinism, and termination.

As originally proposed, type classes provide overloading and ad-hoc definition, but can still
be understood (and implemented) in terms of strictly parametric calculi. This is not true of
subsequent extensions of type classes. Functional dependencies and equality constraints allow
the satisfiability of predicates to refine typing; this means that the interpretations of
equivalent qualified types may not be interconvertible. Overlapping instances and instance
chains allow predicates to be satisfied without determining the implementations of their
associated class methods, introducing truly non-parametric behavior. We propose a new approach
to the semantics of type classes, interpreting polymorphic expressions by the behavior of each
of their ground instances, but without requiring that those behaviors be parametrically
determined. We argue that this approach both matches the intuitive meanings of qualified types
and accurately models the behavior of programs.

Recently, Wadler presented a continuation-passing translation from a session-typed functional
language, GV, to a process calculus based on classical linear logic, CP. However, this
translation is one-way: CP is more expressive than GV. We propose an extension of GV, called
HGV, and give translations showing that it is as expressive as CP. The new translations shed
light both on the original translation from GV to CP, and on the limitations in expressiveness
of GV.

Type classes, first proposed during the design of the Haskell programming language, extend
standard type systems to support overloaded functions. Since their introduction, type classes
have been used to address a range of problems, from typing ordering and arithmetic operators to
describing heterogeneous lists and limited subtyping. However, while type class programming is
useful for a variety of practical problems, its wider use is limited by the inexpressiveness
and hidden complexity of current mechanisms. We propose two improvements to existing class
systems. First, we introduce several novel language features, instance chains and explicit
failure, that increase the expressiveness of type classes while providing more direct
expression of current idioms. To validate these features, we have built an implementation of
these features, demonstrating their use in a practical setting and their integration with type
reconstruction for a Hindley-Milner type system. Second, we define a set-based semantics for
type classes that provides a sound basis for reasoning about type class systems, their
implementations, and the meanings of programs that use them.

Type classes have found a wide variety of uses in Haskell programs, from simple overloading of
operators (such as equality or ordering) to complex invariants used to implement type-safe
heterogeneous lists or limited subtyping. Unfortunately, many of the richer uses of type
classes require extensions to the class system that have been incompletely described in the
research literature and are not universally accepted within the Haskell community.

This paper describes a new type class system, implemented in a prototype tool
called ilab, that simplifies and enhances Haskell-style type-class programming.
In ilab, we replace overlapping instances with a new feature, instance chains,
allowing explicit alternation and failure in instance declarations. We describe a technique
for ascribing semantics to type class systems, relating classes, instances, and class
constraints (such as kind signatures or functional dependencies) directly to a set-theoretic
model of relations on types. Finally, we give a semantics for ilab and describe its
implementation.

Hackage, an online repository of Haskell applications and libraries, provides a hub for
programmers to both release code to and use code from the larger Haskell community. We suggest
that Hackage can also serve as a valuable resource for language designers: by providing a large
collection of code written by different programmers and in different styles, it allows language
designers to see not just how features could be used theoretically, but how they are (and are
not) used in practice.

We were able to make such a use of Hackage during the design of the class system for a new
Haskell-like programming language. In this paper, we sketch our language design problem, and
how we used Hackage to help answer it. We describe our methodology in some detail, including
both ways that it was and was not effective, and summarize our results.

Some of these papers are copyright ACM. These are the author's versions of the work.
They are posted here by permission of ACM for your personal use. Not for redistribution.
Please see each paper for the location of the definitive version.