The language was right. The tooling was not.
Haskell has been called niche for thirty years. That framing assumes a world where humans write all the code. In a world where AI writes most of it, the language that wins is the one where correctness is checkable. Haskell is not niche in that framing. It is early.
The pattern has not changed
Every programming language carries the fingerprints of its intended author. Assembly was shaped by people who thought about registers. C was shaped by people who built operating systems. Python was shaped by people who wanted to get things done without ceremony. Each layer of abstraction made the one beneath it less essential by absorbing it into something higher level. Machine code did not disappear. It became a target. Assembly did not disappear. It became the thing a compiler emits.
For seventy years the author was a human being. That assumption is now changing.
If AI becomes the primary author of code, it follows that the language should adapt to the new author’s strengths and weaknesses. This is not a break from the pattern. It is the pattern, doing what it has always done. The next layer is being written right now, and source code is the thing about to be demoted — not deleted, demoted, the way assembly survives today: indispensable, specialized, and no longer the layer most people author.
When generation is cheap, verification is the bottleneck
A model can produce plausible code in seconds. Plausible code is cheap, and plausible code is often wrong. The hard part was never typing the characters. It was knowing they were correct.
So the bottleneck moves. When writing code is free, the scarce, valuable, load-bearing work becomes proving the code does what it should. The generator does not need to be trusted. The artifact needs to be checkable. That single sentence is the center of the whole shift.
This reframes what a good language for AI-authored code even is. It does not need to make the model feel clever. It needs to make wrongness cheap to detect.
Two ways to write a language for machines
There are two honest answers to “what should a language look like when machines write it,” and they are not the same answer.
The first reduces noise in the loop. Make the language explicit and unambiguous so the model has fewer ways to be subtly wrong, then let it iterate against the compiler until the errors stop. This is the iterate-until-green path. It works, and it is real.
The second changes the signal entirely. Instead of describing how to do something step by step and hoping the steps are right, you describe what must be true and let the compiler verify it. The model does not simulate execution in its head, which is its weakness. It describes a transformation and lets the proof checker confirm it, which is its strength.
We are building for the second path. Not because the first is wrong, but because the second is stronger where it matters, and the language for it already exists.
Why Haskell
In Haskell, a well-typed function is not just code. It is a proof that a certain transformation is valid, and the compiler is the proof checker.
When you encode your invariants in the type system, illegal states become unrepresentable. A draft document has no reviewer because the type does not have that field. A parsed value cannot be confused with an unparsed one because they are different types. Effects are explicit: a signature tells you whether a function touches the outside world, can fail, or is pure, and the compiler enforces it. The information is right there, checked, every time.
This is what “correct by construction” means. Correctness is not iterated into the code after the fact. It is the load-bearing structure the code is built on. In the happy path, there is no feedback loop to run, because there is nothing to converge toward. It was right when it compiled.
The model does not need to be right. It needs to be checkable. Haskell makes more of “right” checkable than any other production language.
The compiler as a meaning engine
Source code is a lossy compression of intent. We have always known this, which is why we surround it with the uncompressed version: tests, docs, design records, runbooks, assertions, observability. We spend enormous effort reconstructing what the author meant from what the author wrote.
When generation is cheap, the uncompressed version is what we should be authoring. The unit of software stops being a file of instructions and becomes a semantic artifact: intent-first, explicit about effects, verifiable, reproducible, explainable. And the thing that turns intent into a running system — that checks everything it can, optimizes everything it can, and refuses to stay quiet about what it cannot prove — is the compiler.
Haskell is verbose in exactly the right places. Not verbose like boilerplate. Verbose like meaning. A compiler built for this era should lean into that: see as much as possible, check as much as possible, and report what it finds in terms the next author — human or model — can act on.
The bottleneck was the tooling, not the language
None of this is new. GHC is one of the most sophisticated compilers ever built, and its type system has been production-ready for decades. The language was right.
The surrounding infrastructure was not. Package management fragmented into overlapping, incompatible approaches. Build times stayed long. Cross-compilation stayed painful. Setting up a Haskell project from scratch in 2026 still involves more friction than it should. The ideas deserved better infrastructure than they had.
So that is what we are building.
hx is the toolchain — install, resolve, build, test, format, lint, publish, all in one fast binary. It is written in Rust on purpose: a toolchain should not share its dependencies with the thing it manages, and a static Rust binary starts in milliseconds, ships as one file, and cross-compiles trivially. We write the tooling in Rust, but we think in Haskell.
BHC, the Basel Haskell Compiler, is a clean-slate compiler that compiles the same language with the same type safety, but offers runtime profiles — default, server, numeric, edge, realtime, embedded — each a different performance contract, selected by one flag. Same source. Same guarantees. Different envelopes.
The tooling is not separate from the thesis. The tooling is the thesis.
We are copying what works
We did not invent this playbook. Rust did.
Rust is a hard language, but its ecosystem is not. Cargo made starting a project, adding a dependency, running the tests, and publishing a package a single obvious tool away. And the compiler earns its reputation — it catches an enormous class of bugs before the program ever runs, and it explains them in terms you can act on. A great language, with effortless ergonomics, behind a relentlessly thorough compiler: that is the combination that wins adoption.
That is the combination we want for Haskell. hx is the effortless part — one binary, one command to install the toolchain, one command to build, deterministic from the lockfile up. BHC is the relentless part — a compiler that checks as much as it possibly can at compile time, and reports what it finds in terms the next author, human or model, can use.
And we intend to add more checks, not fewer. In a world where the code is generated, every additional thing the compiler can prove is one more class of wrongness that never reaches production. More static analysis. More exhaustiveness. More of the runtime contract pulled forward into the type system. The compiler that sees the most and says the most is the one you want standing between a generated artifact and a running system.
The bet
We have a conviction, not a crystal ball.
If the broader bet is wrong — if Haskell never has its revival, if the industry settles on a different language for the machine-authored era — the work still stands on its own. Fast Rust-based tooling, deterministic lockfiles, runtime profiles, and structured, machine-readable diagnostics are valuable for any Haskell project today, regardless of what happens next. We would rather have tried and been wrong than watched from the sidelines.
And the job changes for everyone, not just for us. If the machine writes the code, the human defines constraints, shapes intent, and evaluates outcomes. The unit of work becomes the obligation, not the function — closer to architecture than to authorship. The compiler still has to verify the result. We are making that verification load-bearing — and, in the commons, cumulative: proven once, named, and shared, so the next author builds on it instead of deriving it again.
All beginning is Haskell. The rest is implementation.