Favourite language
Haskell.
I've been writing software for more than thirty years. I've shipped production systems in C, C++, Java, Objective-C, Python, JavaScript, Rust and a handful of things that never made it to Wikipedia. None of them feel like Haskell. Haskell is the language where the type system is working with you rather than around you — where the compiler is an ally, not a tollbooth.
This is a collection of writing, talks and advocacy for what I think is the best substrate for correct software in 2025 — and, as it happens, the best substrate for agentic coding by a wider margin than the conventional wisdom suggests.
The case
Why Haskell.
Not because it's fashionable — it never has been. Because of what it lets you do that other languages make you paper over with tests, comments and crossed fingers.
The compiler is an oracle
GHC's type system catches not just syntax errors but semantic ones — impossible states, missing cases, wrong units, incorrect compositions. If it compiles, entire categories of bugs are ruled out before the code ever runs. I've been writing statically typed code for thirty years; nothing else comes close to Haskell's compile-time surface area.
Purity bounds your blast radius
Referential transparency means a pure function can be read, tested and refactored without examining what its callers might be doing to shared state. When a type signature is preserved, behavior changes are confined. When it changes, the compiler enumerates every affected site. Refactoring in Haskell is surgical in a way that refactoring in imperative code never quite manages.
Make illegal states unrepresentable
This phrase is older than Haskell, but Haskell makes it practicable. Algebraic data types let you model exactly the states that can legitimately exist and no others. A value of type `NonEmpty a` cannot be empty; a value of type `Validated e a` cannot be simultaneously valid and invalid. You stop defending against impossible inputs everywhere because you stopped making them possible.
Concurrency that composes
Software Transactional Memory gives you composable, deadlock-free in-process transactions on mutable state. Lightweight green threads scale to hundreds of thousands of concurrent operations without OS-thread overhead. Async exceptions propagate cleanly through typed effect stacks. Concurrent Haskell is not an afterthought — it was designed in.
Extraordinarily well-suited to agentic coding
The same properties that make Haskell powerful for humans make it extraordinary for LLM agents. The agent gets compile-time feedback at every edit. The blast radius of a change is bounded by what the type system says it can be. The cost of iterating toward correct code is lower than in any mainstream alternative. Haskell was not designed for this — it turns out to be a happy accident.
Expressive without being clever
Haskell's core abstraction vocabulary — algebraic types, type classes, parametric polymorphism, monadic composition — has been stable for decades. New Haskell code written against these primitives composes cleanly with old Haskell code. The language rewards a style of design where things that are different look different at the type level, and things that are the same share an abstraction.
Writing
Essays on Haskell.
Long-form arguments for why Haskell matters now — and matters more than it did before agentic coding changed the economics.
-
May 2025
LLM-Driven Software Development
A practitioner's guide to directing LLMs as coding agents — from requirements to deployment
The programmer is being replaced; the engineer is not. A principled five-phase process for harnessing LLM coding capability without losing the discipline that makes software good.
Read essay → -
May 2025
Haskell for Agents
A Strong Substrate for AI-Driven Development, and a Path to Make It Stronger
Haskell's strong types, purity and monadic effect tracking make it an unusually good substrate for agentic coding — for reasons its designers never intended.
Read essay → -
May 2025
The Three-Tier Stack
Substrate Fitness in the Age of Agentic Software Development
Human intuition, LLM scale, and the language substrate form a three-tier partnership. Evaluating programming languages without reference to all three tiers produces the wrong answers.
Read essay →
Talks
Presentations.
Talks given at seminars, meetups and internal sessions. Slides available on request where not publicly linked.
Bridging the paradigm chasm
A ground-up introduction to Haskell aimed at developers fluent in imperative languages. Starts with Hello World and teases apart why the apparent similarity is a trap — covering IO and do-notation, monadic bind, living without assignment, and the productivity argument for pure functional programming. Includes a worked comparison of the same algorithm in Python vs Haskell, and a "Fish Diagram" showing how data flows differently when you stop mutating state.
Slides available on request
Further reading
Starting points.
The resources I'd point someone to if they're serious about learning Haskell properly.