Irken
A statically typed, self-hosting variant of Scheme that pairs Lisp syntax with an ML-style type system, compiling through continuation-passing style to C.
Created by Sam Rushing
Irken is a statically typed programming language created by Sam Rushing that sits squarely between two great traditions: it is, in its author’s words, “a statically typed variant of Scheme. Or a lisp-like variant of ML.” It keeps the parenthesized s-expression syntax and macro extensibility of the Lisp family while layering on the kind of strong, inferred type system more usually associated with the ML family. The result is a small, compiled language that aims to combine the safety and expressiveness of ML with the metaprogramming freedom of Scheme, and to do so while generating efficient native code.
History & Origins
Irken first appeared publicly in May 2011, when Sam Rushing began committing it to GitHub. Rushing is a long-time systems programmer known for early asynchronous-networking work in the Python world, and that background is visible throughout Irken: a recurring goal of the project is to make it practical to build massively scalable systems without threading. Rather than leaning on operating-system threads, Irken compiles programs in continuation-passing style so that the language’s own control flow — not the C call stack — carries the weight of concurrency.
The compiler was originally written in Python and emitted C. Over time the project became self-hosting: the compiler was rewritten in Irken itself and is now bootstrapped from committed bytecode, with the build process running through multiple compilation stages that verify the results against one another. The repository is, fittingly, mostly Irken source.
The language drew attention in the broader programming community around 2014, when it was discussed on Hacker News as “a Scheme with parametric polymorphism” — a concise summary of what makes it distinctive.
Design Philosophy
Irken’s central bet is that you do not have to choose between Lisp’s flexibility and ML’s safety. From Scheme it inherits:
- S-expression syntax — code is written and read as nested lists
- Macros — syntactic extension, so new constructs can be added in the language itself
- A small, regular core that is easy to reason about
From ML it inherits:
- Static typing with type inference — types are checked at compile time but rarely need to be written out
- Parametric (“let”) polymorphism — functions can be generic over types
- Algebraic data types and pattern matching — structured data and exhaustive case analysis
On top of this, Irken adds row polymorphism for records, a feature that neither Standard ML nor Haskell provides in the same form.
Key Features
A Lisp That Type-Checks
Irken programs look like Scheme, but every expression is type-checked before compilation. Type inference means most of that checking happens without explicit annotations.
| |
Algebraic Data Types and Pattern Matching
Irken supports sum types and pattern matching in the ML tradition, expressed with Lisp syntax.
| |
Row Polymorphism
Records in Irken are compile-time structures, similar to C structs, but their types are checked structurally: a record is compatible with a record type if it simply contains the right fields, with no explicit declaration required. Row polymorphism lets a function accept records that carry extra fields without discarding them — solving the classic “loss of information” problem of structural subtyping by threading the extra fields through as a polymorphic type variable, written with an ellipsis.
| |
| |
Continuation-Passing Style for Concurrency
Internally, after type checking and optimization, Irken transforms programs into a CPS register-machine representation before emitting code. Because control flow does not rely on the C stack, the design is intended to support very large numbers of concurrent activities cheaply — the same problem space Rushing’s earlier asynchronous-networking work targeted, but with static type safety.
Compilation and Implementation
Irken offers more than one backend:
| Backend | Notes |
|---|---|
| C | The default; compiles via clang or gcc to native code |
| LLVM | An alternative native backend |
| Bytecode / VM | Reportedly about 3-4x slower than compiled code (per the project’s README), but with a faster build-and-test cycle |
A notable constraint of the implementation is that it depends on tail-call optimization being enabled — the generated code cannot be compiled with optimization disabled. The project is released under the permissive BSD-2-Clause license.
According to the repository, the compiler has been built and tested on a handful of 64-bit platforms, including amd64 macOS, amd64 FreeBSD 11, amd64 Linux (Ubuntu), and aarch64 Linux (Debian on the Raspberry Pi 3). As with any small research compiler, support outside the configurations the author has exercised should not be assumed.
Evolution
Irken has grown steadily rather than through formal numbered releases — it lives as an evolving GitHub project. Significant milestones include the merge of a bytecode/VM backend in March 2017 and a foreign-function-interface system in August 2018, which made it easier to call into existing C libraries. Maintenance continued into the early 2020s, with 32-bit fixes around 2019–2020 and bootstrap refreshes; the most recent commits date to May 2021.
Current Relevance
Irken is best understood as a research and hobbyist language rather than a production platform with a large ecosystem. Its audience is people interested in:
- Type systems — particularly row polymorphism and structural typing of records
- Compiler construction — a compact, self-hosting compiler that bootstraps from bytecode
- CPS-based concurrency — building scalable systems without threads
- Lisp/ML synthesis — what a typed Scheme can look like in practice
Anyone exploring Irken should expect a small community and the rough edges typical of a single-author research language, alongside an unusually coherent and instructive codebase.
Why It Matters
Irken matters because it demonstrates, in a working and self-hosting form, that the Lisp and ML traditions are not opposites. It keeps the syntactic openness and macro power that make Scheme a joy for metaprogramming, yet refuses to give up the compile-time guarantees of an inferred, polymorphic type system — and it pushes that type system further than the mainstream ML languages by making row-polymorphic records first-class. For language designers, it is a compact, readable case study in how to fuse two influential families into a single coherent compiler.
Timeline
Notable Uses & Legacy
The Irken Compiler Itself
Irken is self-hosting: after an initial Python implementation, the compiler was rewritten in Irken and is bootstrapped from committed bytecode, making the compiler its own largest program.
Scalable Concurrent Systems Research
Irken was designed to host massively scalable systems without relying on OS threads, using continuation-passing style so that concurrency does not depend on the C stack.
Type-System Experimentation
Its support for row polymorphism gives a practical testbed for structural typing of records, a feature absent from Standard ML and Haskell.
Studying Lisp/ML Hybrids
Irken serves as an instructive example of marrying Lisp's s-expression syntax and macros with an ML-style inferred type system and algebraic data types.