Choreographic Programming
Write a whole distributed system as one script, and let the compiler split it up.
A distributed system is normally written as many separate programs, one per participant, which have to agree on a protocol that exists nowhere in the code. Choreographic programming inverts this: you write the interaction once, as a single program that names every participant, and a compiler projects it onto the individual endpoints. Protocol mismatches and whole classes of deadlock stop being bugs you debug and become programs you cannot write in the first place.
My work here follows three lines.
What choreographies are: we showed that choreographic and multitier languages (developed independently in the process-calculus and lambda-calculus communities) are separated by just two things, perspective and how communication is modelled, and gave translations between minimal versions of both, opening a route for results to cross over.
Making them useful: Prisma carries the idea into decentralized applications, compiling one program into a smart contract plus its client, with a proof that a malicious client cannot drive the contract off-protocol.
Putting the theory on machine-checked foundations: together with the PhD students I work with, we are rebuilding choreographic metatheory in Lean, where state transformers replace variable binding, dependent types eliminate the “impossible” branches that plague embedded choreographic libraries, and deadlock-freedom is decoupled from any particular compiler.
- 🏅 Distinguished Paper Multiparty Languages: the Choreographic and Multitier Cases, ECOOP 2021
Timeline
Multiparty Languages: the Choreographic and Multitier Cases
Problem. Choreographic languages and multitier languages both describe a multiparty system as one program instead of many separate ones, but they grew out of different theories (process calculi vs. lambda calculus) in two communities that had little contact, so it was unclear whether results from one side could transfer to the other.
Idea. Two things separate them. The first is perspective: a choreography describes the system objectively, from the outside, like a play script naming every role; a multitier program describes it subjectively, hopping from one participant’s first-person viewpoint to another’s. The second is how communication is modelled: manifest in a choreography, where every interaction is written down, and non-manifest in a multitier program, where it is implied by where values are used.


Fig. 1/2 from the paper.
Result. Once both differences are isolated, translation algorithms in each direction follow, given for Mini Choral and Mini ScalaLoci, minimal languages stripped to the essentials of each paradigm. That opens the door to sharing results across the two communities: compiling a choreography via a multitier compiler to reuse its per-participant code generation, say, or translating a multitier program into a choreography to check statically that it only performs its intended communications.
Links: ECOOP 2021 · paper · video 🏅 Distinguished Paper
Prisma: A Tierless Language for Contract-Client Protocols

Problem. A decentralized app splits contract and client into two separate programs (e.g. Solidity and JavaScript), so their interaction protocol only exists as a convention in the programmers’ heads. A client that sends messages out of the intended order can force the contract off-protocol (a common source of exploited, costly bugs).
Idea. Write contract and client as one program, marking each declaration with where it lives, and use a single construct that expresses “the contract actively waits for a specific client to act” as ordinary control flow, instead of a hand-checked convention split across two files.
Result. A compiler splits the single program into a client and a smart contract, with a formal proof that a malicious, attacker-controlled client can never force the compiled contract off the source-level control flow: the protocol is enforced by construction, not by a hand-written state machine.
Links: TOPLAS 2023 · ECOOP 2022 · extended abstract · artifact · github · arxiv
Mechanizing Choreographic Programs and Hoare Logic
Problem. Formally verifying choreographies in a proof assistant is notoriously painful, because most choreographic languages are functional (receiving a message introduces a fresh variable), and machine-checked proofs about variable binding and substitution end up dominating the whole effort.
Idea. Give every participant a local state of an arbitrary type, and model “receive a message” not as binding a new variable, but as a plain function from (old state, message) to new state (a state transformer). Receiving a message then introduces no binder at all.

Result. A full mechanization (in Lean) proving soundness and completeness of endpoint projection, deadlock freedom, confluence, and a Hoare logic for choreographies, sidestepping the binding and substitution reasoning that usually dominates such a development.
Links: arxiv
On Eliminating the Impossible with Dependent Types

Problem. Choreographic libraries embedded in a host language (Haskell, Rust, …) still have a gap: a “located” value that a role may or may not own is modelled as an option type, and unwrapping it always keeps a dead “impossible” branch (ruled out only by the library author’s discipline, never by the type checker).
Idea. In a dependently-typed host language, make “this role owns this value” a genuine machine-checked proof rather than a runtime tag: a located value’s type carries a proof that the current role is among its owners.
Result. A choreographic library where no error/undefined appears anywhere in the core implementation: totality is enforced by the compiler itself, without sacrificing expressivity relative to prior, partial libraries.
Links: arxiv
2026Unpublished draft (click to expand)Choreographies First, Session Types Later
Choreographies First, Session Types Later
Problem. With multiparty session types, you write a global protocol and the individual processes by hand, and keep both in sync yourself. Choreographic programming instead lets you write one program and generate the processes, but classically the deadlock-freedom proof is tied directly to that specific compiler: hand-edit a generated process afterwards, and the guarantee is gone.
Idea. From the choreography, automatically infer a global type, and project one local type per role, then prove deadlock-freedom purely from the fact that each process implements its local type, independently of how that process came to be.



Fig. 1 from the paper.
Result. Any process that type-checks against its role’s local type keeps the whole system deadlock-free, including a process nobody generated from a choreography at all, as long as it was checked against that local type.
Links: preprint