Typing Composable Coroutines
Qiqi Gu, Wei Ke
TL;DR
The paper addresses the challenge of reasoning about asynchronous coroutine behavior by introducing a dependent-type based coroutine type notation and a composition calculus that combines a list of coroutine types into a single, checkable type using a compose function $\bm{\circ}$. It defines a formal grammar for coroutine types, eight composition rules, and analyses of type complexity $N$, termination, and evaluation order, supported by proofs of soundness and multiple language-agnostic applications. Key contributions include a practical framework for modeling data flow through yielding and resuming across first-class, stackless coroutines, plus concrete demonstrations in Python, OCaml, and Prolog to illustrate how complex control-flow patterns (mapping, file I/O, pattern matching, and goal-driven proof) can be typed and composed. The work enables static type checking of coroutine groups in single-threaded schedules and lays the groundwork for integrating coroutine typing into existing languages, with future directions toward polymorphism, inheritance, and deeper type-narrowing capabilities.
Abstract
Coroutine, as a powerful programming construct, is widely used in asynchronous applications to replace thread-based programming or the callback hell. Using coroutines makes code more readable and maintainable, for its ability to transfer control while keeping the literal scope. However, reasoning about coroutine behavior can be challenging without proper typing. We propose a type notation and calculus for composing asymmetric, first-class, stackless coroutines. Given the types of a list of coroutines, we can compute a composed type matching the collective behavior of the coroutines, so that the input and output can be type-checked by a type system. Our coroutine types can model the data received by or yielded from a coroutine, which be of coroutine types as well. On top of our type calculus, we discuss its soundness and evaluation issues, then provide four application scenarios of our coroutine types. Not only can our types be used in modern programming languages, such as Python, but also model program behaviors in OCaml and even Prolog.
