Programming Languages
From Turing's computable numbers to verified compilers and dependent types — the type theories, semantics, and verification techniques that decide what counts as a correct program.
Minimum viable reading path
The 7 papers that give you most of the field's mental model, in reading order.
- On Computable Numbers, with an Application to the Entscheidungsproblem
- An Axiomatic Basis for Computer Programming (Hoare Logic)
- A Theory of Type Polymorphism in Programming
- Monads for Functional Programming
- RustBelt: Securing the Foundations of the Rust Programming Language
- LLVM: A Compilation Framework for Lifelong Program Analysis & Transformation
- CompCert: A Formally Verified Optimizing Compiler
01 On Computable Numbers, with an Application to the Entscheidungsproblem MVRP
Defines a universal computing machine and proves the undecidability of the halting problem.
The founding document of computer science. Read it once carefully; everything else is footnotes.
Basic logic, mathematical maturity
Computation has a universal model — and inherent limits no clever programming can escape.
02 An Unsolvable Problem of Elementary Number Theory (Lambda Calculus)
Introduces the λ-calculus — function abstraction, application, and reduction — as a model of computation.
The conceptual ancestor of every functional language; required to read modern type-theory papers.
Basic logic
Functions and substitution are enough to express any computation.
03 Recursive Functions of Symbolic Expressions and Their Computation by Machine (LISP)
Introduces LISP, with eval, apply, and the s-expression as both code and data.
A foundational language paper; the conceptual seed of every later language with first-class functions.
Lambda calculus, basic recursion
A small set of primitives is enough to bootstrap an entire language.
04 An Axiomatic Basis for Computer Programming (Hoare Logic) MVRP
Introduces a formal logic for reasoning about program correctness with pre- and postconditions.
The foundation of program verification; you can't read modern verification papers without this.
First-order logic
You can specify what a program does separately from how it does it, and prove they match.
05 Communicating Sequential Processes
Models concurrency as communication between independent processes via synchronous channels.
The intellectual ancestor of Go's channels and Erlang's actor model.
Basic concurrency, first-order logic
Concurrency is communication, not shared memory.
06 Towards a Theory of Type Structure
Introduces System F (parametric polymorphism) and the underlying theory of polymorphic types.
The theoretical foundation under generics in every modern typed language.
Lambda calculus, basic type systems
Polymorphism can be a precise type-theoretic concept, not just a programming convenience.
07 A Theory of Type Polymorphism in Programming MVRP
Proves type-correctness for polymorphic functional programs and introduces type inference.
The paper that gave us ML and the entire Hindley–Milner family of inferred type systems.
System F, unification
Polymorphism plus type inference is decidable and practical.
08 Principal Type-Schemes for Functional Programs (Damas–Milner)
Algorithm W — the type inference algorithm under every ML, Haskell, and Scala compiler.
The algorithmic backbone of every Hindley–Milner type system in production today.
Milner type polymorphism, unification
Type inference is a constraint-solving problem with a clean algorithmic solution.
09 A Syntactic Approach to Type Soundness
A clean technique for proving type soundness via progress and preservation lemmas.
The default proof structure for type soundness in modern PL papers; conceptually essential.
Operational semantics, basic type theory
Type soundness is two lemmas: well-typed programs don't get stuck and types are preserved.
10 Monads for Functional Programming MVRP
Shows how the category-theoretic notion of monad gives a clean handle on side effects in pure languages.
The conceptual unlock for I/O, state, and exceptions in pure functional languages.
Lambda calculus, basic Haskell helpful
Side effects can be threaded through pure code as values of a parameterised type.
11 Definitional Interpreters for Higher-Order Programming Languages
Introduces continuation-passing style and definitional interpreters as semantic specifications.
A foundational paper for understanding programming-language semantics and continuations.
Lambda calculus, basic interpreters
You can specify a language's meaning by writing an interpreter for it in another language.
12 Region-Based Memory Management
A static analysis that infers stack-like region annotations to manage memory without GC.
A conceptual ancestor of Rust's lifetimes and a beautiful application of type inference to memory.
Type theory, lambda calculus
Compile-time region annotations can replace runtime garbage collection in a typed setting.
13 RustBelt: Securing the Foundations of the Rust Programming Language MVRP
A formal Iris-based proof of soundness for a substantial subset of Rust's type system.
The right reference for understanding why Rust's ownership system is actually sound.
Region-based memory management, separation logic
Even unsafe code can be encapsulated soundly inside a strongly-typed language.
14 Efficiently Computing Static Single Assignment Form (SSA)
An efficient algorithm for converting programs to SSA form using dominance frontiers.
The single most important compiler IR transformation; under every modern optimiser.
Compilers, control-flow graphs
A canonical IR where every variable is assigned once unlocks dataflow analysis at scale.
15 LLVM: A Compilation Framework for Lifelong Program Analysis & Transformation MVRP
A compiler infrastructure designed for lifetime analysis and transformation, with a typed SSA IR.
The infrastructure under Clang, Rust, Swift, Julia, and most modern compilers.
SSA, basic compilers
A clean, typed, modular IR is the right substrate for an entire family of language tools.
16 A Catalogue of Optimizing Transformations
The original catalogue of compiler optimisations: constant folding, CSE, dead code, code motion.
Older than most readers, but the optimisation taxonomy is essentially unchanged.
Basic compilers
Most "modern" compiler optimisations were already named and described in 1972.
17 Liquid Types
Refinement types with logical predicates inferred via abstract interpretation.
A practical sweet spot between full dependent types and plain Hindley–Milner.
Type inference, basic logic
Predicate-rich types can be inferred automatically — and that changes who can use them.
18 CompCert: A Formally Verified Optimizing Compiler MVRP
A C compiler whose every optimisation is formally proved correct in Coq.
A landmark in formal verification; proves you can verify a real-world piece of software.
Coq, semantics, compilers
A real, optimising compiler can be proven correct from end to end.
19 The Coq Proof Assistant: Reference Manual / Calculus of Inductive Constructions
The dependently-typed calculus and proof assistant that has formalised much of modern mathematics.
The most influential proof assistant of the last 30 years; the verification toolkit of choice.
Lambda calculus, type theory
A dependently-typed language can serve simultaneously as a logic and a programming language.
20 The Lean Theorem Prover (System Description)
A modern dependently-typed proof assistant with a clean elaboration framework and serious automation.
The proof assistant of the future-decade; behind the formalisation of large mathematical results.
Coq, type theory
A well-designed elaborator and tactic framework can make formal mathematics genuinely productive.