52 Comments

noelwelshJul 10, 2026
Wow. Not a Haskell user, but a big user of other languages with expressive type systems (mostly Scala; some Rust). My experience is the complete opposite. I can't imagine using a language without a good type system to catch all the junk the LLM produces. In fact I thought people would move away from languages from poor type systems, like Python, given the cost of using languages with expressive type systems has decreased with LLMs.
ffreireJul 10, 2026
IME Python has been very pleasant to use with types, even though they are not nearly as expressive as Haskell. I've noticed a shift in my own work where I spend more time playing with/manipulating change than I do making sure things type check. That does happen, of course, but it happens with less frequency then when I was writing Haskell by hand. During that time, I'd have stack running tests on file change and it was pretty smooth as well, but that workflow breaks down a bit with the current generation of agent harnesses we have.
giraffe_ladyJul 10, 2026
I'm pretty sure that's the general trend and it will continue.

But I do think what benefits LLMs is the speed and accuracy of feedback. Type systems cover the accuracy part, but haskell was killing them on speed. It seems like a strange choice to go so far the other way on accuracy when there's a lot of languages in between. But I'm not familiar with the project so not in a position to call it.

It's not also really about expressiveness IMO. I've found LLMs to be best with more constrained type systems: they are better at ocaml than they are at typescript.

TareanJul 10, 2026
Java can also have 15+ minute cold compiles on large projects if you kill all caches. It's less bad on smaller codebases because you don't have to recompile dependencies if you target a bytecode vm, but if you always gate feedback on a cold compile in a fresh VM you just aren't gonna beat an interpreted language

But I'd look at people a bit oddly if they said: 'We didn't want to set up CI caching and compiled languages took 30 minutes per run so we changed our entire codebase to python'.

Maybe it makes sense for them, and caching across dynamically spawned VM's is admittedly a harder problem which most build systems aren't great at, but still. I can easily believe that getting build caching to be reliable would be a lot of work, but is it more work than a full rewrite of a significant codebase?

pjmlpJul 10, 2026
Additionally in modern Java there are even the options of AOT and JIT caches, which can be reused across runs.

Or if staying on Linux, JVM snapshots.

hunterpayneJul 11, 2026
javac doesn't really do a whole lot. Consequently, whatever compile time you are complaining about would be worse with any other compiled language. Most optimization work in Java happens at runtime.
pjmlpJul 11, 2026
First of all I am not complaining about anything.

Secondly, there are several ways how Java source code becomes machine code, depending on which JVM and JDK is being used, not taking into account the ART cousin.

saghmJul 10, 2026
> I've found LLMs to be best with more constrained type systems: they are better at ocaml than they are at typescript.

When the potential set of behaviors you could write a program to have is infinite, but the actual behavior you want is singular, a programming language is more importantly defined by which ones it eliminates up front than which ones it lets you write (assuming it lets you write the one you want at all, but that's almost always going to be the case for most general purpose languages). Bugs are just false positives in this framing, where the program you wrote seems like the one you wanted, but there's some divergence between what you thought you were getting and what you actually got, and catching some of those up front is a huge part of why type systems are so useful.

em-beeJul 10, 2026
exactly, i find the article a wierd take. i would have thougt that being able to catch errors at compile time is the assurance that the LLM generated code is actually decent.

so does this mean that the LLM writes code that is so good that the compiler does not find any more errors?

or is it due to the nature of haskell that makes it hard to write bad code to begin with?

or just that because the haskell compiler catches more errors there is less broken haskell code for the AI to train on?

and what does that mean for the switch to python? if the python compiler/interpreter doesn't catch as many errors do we even know that the code is good?

or is this more like the belief if the LLM can generate good haskell code, surely it can also generate good python?

what's the solution here? speeding up the haskell compiler? if that were easy, would it not already have happened?

personally i still don't trust LLM code generation. i didn't learn haskell yet, but what i hear about it makes me more likely to trust that LLMs can generate good haskell code than python.

i believe the future in LLM code generation is code that can be proven to be correct. proving code correct has been a research topic at some point.

tonyarklesJul 10, 2026
> what's the solution here? speeding up the haskell compiler? if that were easy, would it not already have happened?

I suspect you’ve nailed the answer: it’s probably not easy, although it’s also possible that it just hasn’t ever had a lot of attention paid to it because it’s been generally fast enough for their user base?

antonvsJul 11, 2026
Part of the issue is probably that Haskell build performance is perfectly fine for local development, even on rather large systems.

But in commercial production environments, CI pipelines tend to want to build everything from scratch every time, and that slows everything down. Rust has the same issue. Both languages, by default, compile all their dependencies from source, rather than obtaining precompiled artifacts from a repo the way some languages (like Java) do. And their compilers are slower than e.g. Go's. As the article mentions, various kinds of caching can help with that, but that's extra stuff you have to manage and deal with.

I'm not sure this is a bad thing, though. Haskell co-creator Simon Peyton-Jones coined the unofficial Haskell motto, "avoid success at all costs". I tend to agree with that. It would be difficult for Haskell to maintain its conceptual edge if it were a mainstream commercial language.

cwilluJul 11, 2026
The thing I hate about rust is that compiling a small app immediately creates 100gb of junk, and that junk doesn't live in the responsible project's folder, and that junk doesn't get cleaned up by anything.
pdimitarJul 11, 2026
You're exaggerating quite a lot. Biggest I've seen the cargo directory after 3 months of active Rust development was ~17GB.

You can also limit it with an env var. I have capped mine at 10GB.

kstrauserJul 11, 2026
I’m at 227GB as I write this.
hunterpayneJul 11, 2026
"proving code correct has been a research topic at some point."

It has been an area of active research for 40 years. But almost all the research returned the null result, meaning that the program proving didn't improve code quality (basically it didn't work). Yet somehow a group of programmers, usually fresh out of academia falls for program proving each generation. Strong types do really help but you need a good compiler which is sometimes lacking in the real work cough Scala cough. The problem with strong types and program proving is that the juice just isn't worth the squeeze meaning the extra time taken doesn't result in reduced debugging time or improved code quality. I don't think that changes with LLMs. It just exposes the flaws more quickly.

em-beeJul 11, 2026
what i expect to change with LLMs is the benefit you get from automated testing. which is really what LLMs need. tools that tell you something is wrong may not speed up a human developer, but they will allow LLMs to make corrections by itself until the warnings go away. so while it may not be worth it to a human developer, it may well be worth it for an LLM.
pmontraJul 11, 2026
The issue with formal proofs is that we might end up with correct code that does the wrong thing. I mean, something that the market doesn't care about. At the same time a buggy set of PHP scripts does what people care about and captures the market. Think about 20+ years ago and you find a lot of examples.
psd1Jul 11, 2026
https://xkcd.com/224/ lol

Zuckerberg became rich on php, which grinds my gears almost as much as the genocide thing.

In fairness, my peers at $corp used to ship while I was sad-Wojciech "no you can't create tech debt". The universe is cruel to people who care.

frumplestlatzJul 11, 2026
Well, sure — and the issue with tests is we might end up with well-tested code that does the wrong thing.
frumplestlatzJul 11, 2026
That's literally the opposite of reality; the research and adoption have consistently produced code of extremely high quality, at great cost.

The problem has always been:

- It's extremely labour-intensive, and even small changes to the code can require an enormous amount of new proof work.

- The skills required to formally verify software are very different from the skills required to write it, and the set of people capable of doing so is much smaller.

- Code has to be written with verification in mind, against a specification that expresses invariants that can actually be verified, and that is coherent enough that you can derive useful high-level properties of the system from it.

You needed two teams — verification and development. Verification would always be behind the development team, while also having to feed requirements and design changes back to the developers. Everything slowed to a crawl.

AI changes this. A coherent, verifiable, useful specification isn't easy to write — but it's far easier to write than the software itself, and AI can do most of that work: both drafting the spec and proving that it's consistent and that the high-level properties you actually care about follow from it.

More importantly, a high-level spec is far easier to read and reason about than the reams of code required to actually implement something. Which means:

- AI does the grunt work of writing and proving the spec; humans only have to carefully review that high-level artifact.

- AI writes code it must also prove conforms to the spec, so humans can be assured it's correct without babysitting the AI.

- Changes are driven top-down: evolve the spec first, then have the AI fix the implementation and re-prove conformance.

Our (very, very large) company is rapidly going all-in on formal verification across projects we never would have dreamed of verifying before; the velocity hit and the man-hour cost were only worth paying for truly critical infrastructure.

koito17Jul 10, 2026
Recently had to touch a Python project at work. Just setting up the editor needed me to use 2-3 tools out of: pyright, basedpyright, ruff, ty, mypy, and possibly other tools I'm forgetting that kind of do the same thing but throw errors in different parts of the codebase.

Also, for some reason Optional[T] became deprecated, just as the ecosystem finally embraced types ~3 years ago.

In fact, one my company's greenfield projects decided to use TypeScript instead of Python for the [surprisingly] more consistent tooling, and the fact that the big LLM providers all have official TypeScript SDKs anyway. Also, for agentic coding, LLMs don't seem noticeably worse at TypeScript than Python.

My experience can be summarized as:

- for some reason we need 2-3 static analysis tools just for typechecking

- no tool understands each other's comment directives

- each tool reports a different error in your codebase

- even big libraries (e.g. matplotlib) make half their functions return Any

- you'll be tempted to silence the "partially unknown type" warnings, and you'll have to do it for each tool that's running.

mjr00Jul 10, 2026
> Also, for some reason Optional[T] became deprecated, just as the ecosystem finally embraced types ~3 years ago.

Optional[T] is now T | None. Means exactly the same thing but doesn't require an import. Support for the older syntax presumably won't be removed for a long while regardless.

wizzwizz4Jul 11, 2026
Optional[T] was always just an abbreviation for Union[T, None], anyway: it's unsurprising that they didn't choose to give it its own syntax.
These335Jul 10, 2026
I grew up on python and after working with Java I really came to appreciate types. However I do want to point out that big libraries like mpl pre-date most efforts for typing, so it is no wonder that they arent typed properly. A lot of these libraries are trying to improve this but it will just take some time.
pjmlpJul 11, 2026
Having been around for quite some time, and having used several dynamic languages, my pet peeve isn't types.

Rather I prefer not to be in the same spot I was in 1999 - 2001, with Tcl, and every now and then rewriting code into C, for the application to actually deliver within the performance deadlines.

Python is the only mainstream dynamic language where runtime support for dynamic compilation is such an hassle, where the alternatives do exist, yet are mostly ignored.

DanielHBJul 11, 2026
In my (really large) typescript project we have like 6 static analysis tools running[1]. Steps to get the project running: install nodejs, install package manager, install dependencies, run project.

The main difference is that in the JS ecosystem it is all installed at the project level, you don't need anything globablly installed besides the runtime and package manager (and even the package manager can be auto-installed as well if you set it up that way).

[1]: eslint, biome, prettier, scass linter, graphql-codegen, tsc, tanstack-router codegen. That I remember, might be more (although codegen might not be considered static analysis, it is needed for static analysis).

sheeptJul 11, 2026
Why do you need both Biome and Eslint/Prettier?
ohmahjongJul 11, 2026
I'm not who you replied to, but we use Biome for 99% of the linting/formatting, and then an eslint plugin for a few specific i18n scenarios that Biome doesn't cover.
DanielHBJul 11, 2026
Yeah we had some corner case that still required eslint, although I don't remember what exactly. We also have prettier for a few file types not supported in biome.
OoooooooOJul 11, 2026
You always work in a virtual environment per project in Python, all dependencies are installed in the venv.

So same as JS then.

zelphirkaltJul 11, 2026
Although I also install such tools (linter, import sorter, type checker) locally in my virtualenvs in Python projects. It is possible to do so, but maybe not as straight forward. I have to give the JS ecosystem that much: With the project-local approach, they have done one thing right.
QuothlingJul 11, 2026
UV, Ruff and Pyrefy and you're set. As someone who works with Python, Typescript and C/Zig quite a lot I don't disagree with you on Typescript, but I'm not sure why you'd pick Typescript over Python. Bun is kind of awesome, but it's also kind of unfinished, but if you go with the default Node I find that the setup for security compliance is next to impossible where Python can do most things with it's standard library, a pandas and pyarrow.

I personally prefer the fake typing in Python because it fits well with our defensive programming style with very low abstraction and little to no adherence to DRY. Since Python naturally force you to deal with runetime assertions rather than getting you to do compiletime checks that then don't actually offer any form of safety at runtime. Which is obviously not a very technical argument, but it just feels a lot cleaner rather than having to juggle the two.

bionade24Jul 11, 2026
uv still can't build all wheels and afaik they don't intend to do so. Furthermore they leave their users with 0 indication that the build fails because the wheel is unsupported by uv. If I were a beginnner or intermediate, I'd definitely given up after some attempts of fixing the buildsystem/code of the wheel.

I don't get how uv regularly gets recommended without any note about this.

zelphirkaltJul 11, 2026
Can you name some example and explain what happens, that the user is left without indication of failures? I am asking, because I have not had such issues yet, but maybe I just don't know I had them?
woodruffwJul 11, 2026
(I work on uv.)

Can you say more? uv should always tell you if a wheel build fails, unless the build backend (which uv doesn’t control, unless you use uv’s own backend) decides to silently ignore a wheel build. This would be a bug in any given build backend IMO.

This is an unfortunate complexity in Python packaging: something like `uv build` can dispatch a wheel build for you, but the actual code that gets run as part of that build is often third-party build backend code that uv itself has little to no control over.

QuothlingJul 11, 2026
We get UV to generate a requirements.txt and then use the Python and Pip which is available on the official Microsoft container images we use for Azure container apps once it hits production. I've never had any issues with the build system in development though.
OJFordJul 11, 2026
> for some reason Optional[T] became deprecated, just as the ecosystem finally embraced types

Deprecated in favour of `T | None` exactly because of that embrace. It's cleaner, more consistent (you can `T | U` arbitrarily), and helps slim down the `from typing` imports.

zelphirkaltJul 11, 2026
Yes, changing a type checker tool is not done easily in larger projects, or on the fly, as they all have different edge cases, where they don't infer well enough, or are more lenient than another tool.

I have switched type checker recently in my own Python projects from zuban to ty. ty seems to work better, and is not a one man show/bus factor of 1, though I respect the work that has gone into zuban by its creator. But ty doesn't understand mypy configuration in pyproject.toml ...

I imagine switching a type checker in a bigger project and with more people involved to be a bit of a PITA, until everyone has adjusted their development environment/tooling. Best one can do is research beforehand which tool suits one best, test it, and then stick to it, unless it has unbearable failures.

woodruffwJul 11, 2026
(Note: I work on Python tooling.)

> for some reason we need 2-3 static analysis tools just for typechecking

I don’t follow: you need one type checker, of which you have several options. It’s arguably not ideal to have more than one option, but you should never need to run more than one.

- no tool understands each other's comment directives

In general, all type checkers in Python support the `type: ignore` directive, since it’s standardized.

> each tool reports a different error in your codebase

This is a real problem, but I think you can avoid it (like most people do) by not mixing different tools that do the same thing together.

To my understanding, you’d have the same problem if you combined (e.g.) biome and eslint in a JavaScript codebase.

diegocgJul 11, 2026
If things were that simple...

I have to use more than one Python type checker because there is not a single one that works. Not only different tools catch different issues. They also have different bugs, and different configuration requirements. Different teams have different preferences.

It's a nightmare. If Python taught me something about typing is that a language that doesn't have a clear definition of types in the reference implementation, it will never get it fixed with external tooling.

Pay08Jul 11, 2026
> It’s arguably not ideal to have more than one option

It's a complete ergonomic travesty that Python doesn't have one.

ulrikrasmussenJul 11, 2026
I had a similar experience as you. We normally use Kotlin for everything, but last year we had to do a small project in Python. Setting up the tooling and choosing the tools is quite overwhelming, and the inconsistency between what the tools actually consider type errors is incredibly frustrating. I am actually happy that the project failed and that we don't have to work in that environment anymore.

I think Python is probably good for many things, including scripts and as a starter language, but I don't understand how anyone can stand writing large software systems in it.

calebkaiserJul 10, 2026
I think the author largely agrees with you re: type systems and LLMs. He's pretty explicit that Haskell should be very well positioned to be a power language for LLM-assisted programming, but that the Haskell ecosystem presents the bottlenecks that make it harder.

I don't personally use Haskell for anything, but I use Lean and occasionally some other languages with expressive type systems, and like you I've found it to be a pretty great experience for working with LLMs. But I've also experienced what the author is talking about, with languages that sit at different points on the type system spectrum, regarding a languages ecosystem/infra layer becoming a bottleneck. I don't think it's ultimately about the type system but the broader ergonomics of the language/ecosystem.

So I think his criticism is less than expressive type systems are a pre-LLM concept, and more that Haskell has an individually bad "agentic coding story".

ErroneousBoshJul 10, 2026
> I can't imagine using a language without a good type system to catch all the junk the LLM produces

One approach would be to not use LLMs.

threethirtytwoJul 11, 2026
Another approach is career suicide. Both moves are isomorphic in many companies today and will be pretty much all companies in the future.
ErroneousBoshJul 11, 2026
I don't really understand your comment. Are you saying it's "career suicide" to not use AI slop?
jimbokunJul 10, 2026
You should read the article before replying.
mpweiherJul 10, 2026
TFA:

The type safety we gave up hasn’t been noticeable in any concrete way yet, especially considering our test coverage has never been better.

roenxiJul 10, 2026
It is a bit surprising, I'd have guessed the same. Although in hindsight I could believe that type systems aren't particularly strong as an anti-bug layer. They help. They're a big boon for coordinating large numbers of mid- and low- skill programmers though because it forces them to go further in documenting their function signatures and makes it much more obvious where the problems are when refactoring spaghetti code because things break loudly.

Refactoring spaghetti has become easier in the LLM era because it can just read all the code, and there is now a skill floor on the programmers that kicks in somewhere relatively high. The benefits of type systems might have suffered because of that.

antonvsJul 11, 2026
> I could believe that type systems aren't particularly strong as an anti-bug layer.

They're absolutely huge for this, but you have to write code to take advantage of the guarantees that the type system can offer.

As Yaron Minsky at Jane Street put it, "make illegal states unrepresentable". Stronger type systems make it possible to make more states unrepresentable. You end up with what amounts to static debugging - you debug your code at compile time.

Sure, it's still possible for runtime bugs to occur, but entire classes of bugs are eliminated, plus it becomes possible to have static assurances about program states about things that most language don't even try to express in the type system, like security.

DanielHBJul 11, 2026
Languages like C and Go are so weak in the type system that it barely feels better than fully dynamic languages.
antonvsJul 11, 2026
I agree, I was referring to powerful type systems.
bbkaneJul 11, 2026
At least in C and Go, you can get structs where it's easy to reason about the fields.

In Python, a "class" is simply a dict under the covers and (by default at least) you can add attributes to it after definition (as well as things like properties). So it's difficult to reason about what the fields are at any given time. And that's assuming people USE classes! I've seen code where all the state is in one giant ever-changing dictionary and you have to pull out a debugger just to figure out what's IN the thing! God help you if you mispell a key!

Maybe you work with better quality code than I do, but I find Go's type system a lot easier to reason about than Python's.

japgollyJul 11, 2026
It's about the feedback loop being so slow. Agents often compile and run tests to verify their work
timcobbJul 11, 2026
Right, they run tests too. A compiler is like a quick test before tests. How are you going to cut out that check and let the LLM "write it faster" is beyond me. The compiler catches errors across codebases that today's LLM can't economically or reliably put into context to perform similar checks. They're totally different tools, today.

Also, you can just compile less frequently.

But hey, if LLMs are what drove this person from Haskell to Lisp then all the power to them!

antonvsJul 11, 2026
> But hey, if LLMs are what drove this person from Haskell to Lisp then all the power to them!

I didn't see Lisp mentioned in the article. They moved to Python. Which is certainly a choice.

pjmlpJul 11, 2026
Yeah, basically all the Lisp without the machine code generation machinery.
antonvsJul 11, 2026
Having worked professionally with Common Lisp, I can tell you that’s not even remotely true.

Besides, “machine code generation” is not a fundamental part of Lisp. Some of the most famous implementations were pure interpreters.

pjmlpJul 11, 2026
Such as? Having known Lisp since 1996, and avid digital archaeologist, I wonder which famous implementations are those.
DonHopkinsJul 11, 2026
Even Emacs Lisp has had a byte code compiler since forever, and since Emacs 28 it compiles to native machine code via libgccjit.

Toy lisp interpreters are easy and fun and everywhere, often written in lisp itself, but the same books that teach them go on to teach compilers. SICP chapter 4 is the metacircular evaluator, chapter 5 is the compiler. That ordering is the point: interpretation is the pedagogy, compilation is the destination. Lisp was designed to be easy and efficient to compile (so was Self, and that tech lineage runs straight into HotSpot and V8). The archaeology cuts the other way too: the only famous pure interpreter was LISP I on the 704, and within two years Hart and Levin's Lisp 1.5 compiler (1962) became the first self-hosting compiler in any language, written in Lisp, compiling itself. Lisp practically invented compilation as we know it. And today SBCL doesn't even interpret by default: a form typed at the REPL is native code before it runs. Clojure compiles every form to JVM bytecode.

So antonvs, I'd genuinely like to know which famous implementations you mean, because the honest counterexamples aren't the famous Lisps at all. They're the embeddable extension languages, and I can speak to those from direct experience, not just archaeology.

A digression about Elk, since hardly anybody remembers it and Oliver Laumann deserves the recognition. Elk, the Extension Language Kit, was Laumann's Scheme out of TU Berlin, started in 1987 to be the extension language of the ISOTEXT document editor, released to the world in 1989. Its stated goal was "to end the recent proliferation of mutually incompatible Lisp-like extension languages": instead of inventing yet another one, you linked the Scheme interpreter into your C or C++ application and taught it your app's types and primitives. Emacs-style extensibility as a kit, years before Guile existed. And it was a pure interpreter on purpose. Laumann said it plainly in the USENIX paper: performance was "uninspiring (no compiler is available)" and it didn't matter, because any bottleneck got recoded as a C primitive. The compiled half of an Elk system was the application itself. It shipped that way in real products, including the TELES.VISION video conferencing system, which used Elk continuations as its multithreading mechanism. Elk's embedding design went on to inspire other interpreter authors, including Matz for Ruby.

I hacked on Elk back then and wrote the SPARC port, credited in the Elk 1.2 release notes, and it taught me why "just an interpreter" is never just an interpreter. Elk implemented full call/cc the brute force way: capture the registers setjmp-style, then copy the entire live C runtime stack aside onto the heap, Scheme frames, Xt frames, qsort frames and all, and copy it back whenever the continuation is applied. That works on machines where the stack actually lives in memory. On SPARC it does not: the register windows keep the most recent frames cached in the register file, invisible to any memcpy of the stack. So before copying you trap into the kernel to force every window to spill to RAM (ta ST_FLUSH_WINDOWS), grab the stack while it's momentarily telling the truth, and pray it all lines up with the calling conventions when you copy it back so returns don't sail off into the weeds. Frightening! As hairy as anything inside a code generator. The "simple interpreter" strategy relocates the machine-level work, it doesn't remove it: stack layout, register windows, calling conventions, incremental linking against the running executable so compiled C extensions could be loaded into the interpreter, unexec-style dumping of customized interpreters back out as executables. Compiler and linker work in everything but name.

And look what happened to every extension language that survived: Tcl grew a bytecode compiler in 8.0. Emacs Lisp went from bytecode to native code. Guile, after fifteen years as an interpreter, got a compiler in 2.0 and a JIT in 3.0. Interpreters are how these languages are born. Compilers are how they grow up. Even Ousterhout's own student proved it during the Tcl wars: Adam Sah's Berkeley thesis (TC, 1994, first reader John Ousterhout) got 5-10x by caching parsed representations of values, essentially the design Tcl 8.0 later adopted, and his Rush language with Jon Blow (yes, that Jon Blow) compiled a Tcl-feel language to Scheme at 50-300x stock Tcl. RMS cited Rush by name in the GNU extension language announcement. The Rush source is lost now, which is a small tragedy.

Since Guile came up: Guile existed before the Tcl war, not because of it. Tom Lord had already forked Aubrey Jaffer's SCM into an embeddable library at Cygnus in 1993, called it GEL, and talked RMS into blessing it as the official GNU extension language. The rename to Guile came after trademark trouble, partly because it sounds a bit like "Guy L." The war started when Sun swaggeringly declared Tcl would be "the ubiquitous scripting language of the Internet" and a colleague skunked Tom's Scheme-based GDB GUI project with a quick Tcl/Tk one. Tom vented to RMS, and shortly afterward "Why you should not use Tcl" landed on comp.lang.tcl. Who actually wrote and posted it stayed deliberately murky: the Cygnus NNTP server showed it coming from Tom's dormant gnu.org account, some archived messages have RMS in the From line and Tom's signature at the bottom, and Tom would only ever call it a semi-prank by "the Scheme underground."

Why didn't Guile take over the world? Partly because the plan was always grander than the resources: the idea was one Scheme engine executing many surface languages, including a repaired Tcl and eventually Emacs Lisp itself. But Emacs Lisp turned out to be immovable. It isn't just a Lisp, it's a deeply weird Lisp: dynamic scoping by default, buffer-local variables, text properties, semantics tangled into the C core of the editor. There were decades of plans and experiments to put Emacs on Guile, and Guile 2.x even shipped an Elisp compiler on its VM, but the ecosystem never budged, and in the end Emacs went the other way and grew its own native compiler instead. Guile's own arc is instructive: Andy Wingo gave it a real compiler in 2.0, a register VM in 2.2, a native JIT in 3.0, and it found its killer app in Guix. Not the ubiquitous extension language of GNU, but a living vindication of the design argument Tom was making in 1993: a general Scheme engine underneath, other languages and applications on top.

Tom was a good friend of mine. We argued for decades, about Tcl and Tk and everything else, the way you can only argue with someone who has actually built the thing being argued about. He died suddenly in 2022, and the field is short one fiercely original mind. His body of work and his philosophical posts about extension languages, universal engines, and who gets to control the substrate are a rich source of wisdom that hardly anybody mines. His account of the war is him on the page: brilliant, funny, hard on himself, and fair even to the people who did him wrong. Read it, and the detail I love most for this thread: even Tom, patron saint of the embeddable Scheme interpreter, compiled the performance-critical parts of his Scheme editor with the Hobbit compiler. Nobody stays pure.

An Account of the Tcl War, by Thomas Lord:

https://web.archive.org/web/20110102015130/http://basiscraft...

Glenn Vanderburg's archive of the original flamewar:

http://vanderburg.org/old_pages/Tcl/war/

Elk: The Extension Language Kit, Laumann and Bormann, USENIX Computing Systems, 1994:

https://www.usenix.org/legacy/publications/compsystems/1994/...

I was on all sides of that war at once. Tom and I had heated arguments because I was shipping on the other side: I ported SimCity to Unix with Tcl/Tk, and Tk was the driving factor, not Tcl (and Tcl's weaknesses were real, and Tom and RMS's arguments against it were largely correct: I used Tcl/Tk extensively and pushed them in ways they were not originally designed to be used; multiplayer Tk was a challenge, I had to fix multi-head bugs in X resource management and Tcl UI menu and other mouse-tracking code, and I built a fully functional multiplayer coordinating voting collaborative game on top of it instead of just getting it to draw googly eyeballs on two screens at once; I am painfully aware their arguments are right).

But having an extension language at all is a higher-order bit than having a perfect one, especially when you are designing a GUI toolkit, whose concerns partially overlap those of an extension language. Look at what the X toolkit intrinsics and the toolkits and window managers built on top of them abused X resources for: stringly typed nano-domain-specific languages and semantics and protocols between differently named resources in the same file. Key and mouse bindings, user configuration, fonts and colors and measurements and dimensions and scales, state machines, commands, preconditions, postconditions, parameter bindings, and and and I could go on forever. All of that is what a real extension language is for. Tk worked so well precisely because a real scripting language (no matter how arguably weak) was part of its design from day one, so it never had to badly reinvent one, which is Greenspun's Tenth Rule, the curse of every extensible app before and since.

And the ecosystem kept proving the point: Python's tkinter still embeds a Tcl interpreter with each Tk root, assembles Tcl/Tk command strings, and passes them through _tkinter to be evaluated, and you can register Python functions as Tcl commands and trampoline back across the boundary (the same class of plumbing obsession as SWIG: who owns the glue, and what shape is the trampoline?). Tk never really grew a clean pluggable "bring your own scripting language" extension point; Perl Tk, Ruby's tk.rb, and the rest generally still talk Tcl to the toolkit. The design win is simpler and more Self-like than that: assume a scripting language, any scripting language, is available at runtime, and the toolkit can stay small and SIMPLE.

Which loops back to one of the greatest pieces of language design literature the Tcl War left behind, one that historians and archaeologists will study for centuries: what even counts as a scripting language? Ousterhout's answer was the system-programming-language versus glue-language split, two languages for a large system, typelessness and strings as the uniform wire format between components.

Scripting: Higher-Level Programming for the 21st Century, John Ousterhout, IEEE Computer, 1998:

https://web.stanford.edu/~ouster/cgi-bin/papers/scripting.pd...

I even demoed multiplayer SimCity to Ousterhout in his office at Berkeley.

And then Sun, having hired Ousterhout and his team, then anointed Tcl the ubiquitous scripting language of the internet, pivoted on a dime to Java, got its lunch eaten by JavaScript, a language whose deepest debt is to Self, which Sun also starved. The Self people who left applied the ideas at Animorphic, got bought back, and built HotSpot. As an OG NeWS developer I know exactly how it feels to be promised the world by Sun and left on the back porch in the rain, so I have nothing but empathy for the Tcl/Tk and Self teams. I've been posting these receipts for a decade:

https://news.ycombinator.com/item?id=28669698

https://news.ycombinator.com/item?id=25888450

And the one I treasure, a conversation I had with Tom in 2006, two years before V8, about running into Dave Ungar and the irony that JavaScript credits Self for its prototypes while missing everything else the paper was actually about. It's right there in the title: "Self: The Power of Simplicity." Simplicity first.

And behind that, the two hard tricks that made the simplicity affordable: compiling a radically dynamic language to fast native code, and keeping it debuggable at the same time. That last one is the sleeper. Anyone can pick two of simplicity, performance, and debuggability. Self's dynamic deoptimization let you debug fully optimized code as if it were running unoptimized, source-level, mid-flight, and that machinery went straight into HotSpot too. JavaScript took the prototypes, which were the cheap part:

Self: The Power of Simplicity, Ungar and Smith, OOPSLA 1987:

https://bibliography.selflanguage.org/_static/self-power.pdf

Debugging Optimized Code with Dynamic Deoptimization, Hölzle, Chambers, and Ungar, PLDI 1992:

https://bibliography.selflanguage.org/_static/dynamic-deopti...

https://news.ycombinator.com/item?id=33527618

Which brings this all the way back to Haskell and the article. timcobb joked about being driven "from Haskell to Lisp," but that move would arguably have been more defensible than Python, because the real lesson of seventy years of Lisp is that interpreted versus compiled was never the actual choice. Batch versus incremental is the choice.

andersmurphy and jwr have it exactly right about the REPL. Common Lisp and Smalltalk systems compile one function at a time, to native code, inside the running program, in milliseconds. Avi's headline brag, fixing a bug before the customer hangs up, was routine practice in Lisp shops in the 1980s. NASA once did it to a Lisp system running on a spacecraft a hundred million miles away: the Remote Agent on Deep Space 1 deadlocked in flight, and they diagnosed and fixed it through a REPL running on the spacecraft itself.

Lisping at JPL, Ron Garret's firsthand account of debugging Deep Space 1 in flight:

https://flownet.com/gat/jpl-lisp.html

giraffe_lady named the two axes precisely: speed and accuracy of feedback. GHC gives you accuracy at the price of batch-world speed. Python gives you speed at the price of accuracy. The Lisp lineage, from Hart and Levin through SBCL to the Self-descended JITs your JavaScript runs on today, has been demonstrating for decades that you can have both, if you design the language and the compiler to work incrementally, together, as one live system. And I can't resist pointing out that SBCL's native code compiler is named Python, and carried that name years before Guido picked it for his language. Lisp hackers have been getting sub-second feedback from Python since the 1980s. Theirs emits machine code.

CMU Common Lisp, whose compiler has been named Python since the mid 1980s:

https://en.wikipedia.org/wiki/CMU_Common_Lisp

Oliver Laumann and Tom Lord were exploring exactly these tradeoffs with practical, load-bearing, shipping code while most of the industry wasn't looking. The agents everyone in this thread is arguing about are just the newest programmers to want what Lisp hackers always wanted: a fast, honest conversation with a running system. It would be a shame if we rediscovered everything except the part where it compiles.

pjmlpJul 11, 2026
Great comment Don, should have been one level up on the thread chain, though. :)
DonHopkinsJul 11, 2026
You provoked me by being right, and I just wanted to say that I strongly agree, but it's "nuanced"! ;)

I didn't get a chance to post about my memories of Tom in the hn discussion of his death, because I hadn't really processed it in time to comment, so I'm writing them up now and will publish more later.

But for now, a few memories of Tom Lord, as promised.

In April 2010 Tom posted me a link out of nowhere: "That reminds me (why? I dunno) that - hey: hate man made the news."

Homeless ex-reporter opted for Berkeley streets (SF Chronicle, April 2010, via archive.org):

https://web.archive.org/web/20100413124819/http://www.sfgate...

Hate Man was Mark Hawthorne, a New York Times reporter from 1961 to 1970 who opted out of normal society and spent decades on the streets around Telegraph Avenue and People's Park. He wouldn't talk to you until you told him you hated him. From the Chronicle interview: "It's a new way of hating. It's about being straight with people... My idea is to be straight about negative feelings that we all have, which is what hate is, and then you can have a real conversation."

I replied that I loved Hate Man (but that kind of sounds weird, like I totally missed the point), and that I was honored he'd hated on me once and wished we'd discussed it more deeply, and that he seemed like one of the most sensible people walking around Berkeley.

Then Tom wrote something I've been thinking about ever since. He said that back in the day he'd had some really, really bad days, real existential crises, and that "Hate man and several of the brothers in the park basically saved my life." Hate Man by getting him to play his "let's lean on each other game," the brothers in the park by being good listeners to mumbled words, often enough good counsel, and by whooping his ass at street chess. He described how, as things shut down for the night, Hate Man would gather the rough itinerant runaway kids of Telegraph up in a circle in Sproul Plaza, and they'd all chill and keep safe and share warmth and make peace, "all in the name of Hate. Telegraph was very much a zen temple. Hate man a famous monk."

He also corrected the Chronicle's timeline. The article placed the start of Hate Man's street life in '86, and Tom called bull: Hate Man was the first resident of Berkeley he ever heard of, in 1983, in Massachusetts, from someone who was basically trying to encourage him to run as fast as he could away from the preppy high school that G. W. Bush went to: "There's this guy there. And he's really cool. He likes to shout 'I hate you' at people. And he won't talk to you unless you first tell him that you hate him, too." It made no sense to him at the time. Years later, he said, arriving in Berkeley was like walking into the landscape of a favorite children's book he'd read years before. Many of the familiar characters were there.

I told him that was beautiful.

He replied: "I hate you."

I replied: "Go stick your head in a pig, beeeyatch!"

That's a lyric from Share and Enjoy, the Sirius Cybernetics Corporation jingle from The Hitchhiker's Guide to the Galaxy:

https://www.youtube.com/watch?v=_wSBC5Dyds8

That was sixteen years ago. Tom died suddenly in 2022, and last week I finally took my turn again, on his memorial Facebook page: I HATE YOU!!!!

Hate Man would approve. Be straight about the negative feelings first, and then you can have a real conversation. I hate you, Tom. I miss you.

And if you want one minute of the town where all of this made perfect sense, Tom Lord's Berkeley, here is a shirtless dude riding a cow in the wrong direction up Telegraph Avenue:

Cows In Berkeley? Moooo:

https://www.youtube.com/watch?v=10JSPdTDFsI

I love that town. It suited him perfectly.

timcobbJul 11, 2026
Yes I was being hyperbolic.
yxhuvudJul 11, 2026
The fun part is that the argument holds just as true for humans that write code - we also run tests to verify our work!

Which is basically what people liking dynamic languages have said all the time - types is only good as long as the overhead they bring doesn't cost more.

newaccountman2Jul 11, 2026
I general I agree with you. I think expressive type systems are superior, and they are even better in the LLM era.

I would quibble though that Python's is actually pretty good at this point, and, despite what the below poster is saying, straight-forward to set up and use. I am still perplexed that the author chose Python over Rust or Scala or TypeScript though, especially given they presumably want to migrate a Haskell codebase.

trollbridgeJul 11, 2026
I'm perplexed by that too. We are migrating from Python to Rust simply because Rust is more suited towards unattended agentic loops, and we want to move in that direction. The results you get from a harness/agent/LLM with Rust are simply better than Python because the agent gets much better feedback from the compiler when it makes dumb mistakes. Python doesn't have anything even close to something like SQLx, which is a natural fit in Rust because of how Rust macros work.
newaccountman2Jul 11, 2026
> Python doesn't have anything even close to something like SQLx, which is a natural fit in Rust because of how Rust macros work.

I'd be interested in hearing/discussing more about this. I was very surprised, when I embarked on my side project, that Rust's options for SQL ORMs all seem so weird.

I think what you are referring to is the derivation of FromRow and stuff with SQLx, right?

trollbridgeJul 11, 2026
I don't paticularly want to use an ORM. What SQLx does is a bit different - it statically analyses the SQL in your program against the database and ensures the SQL is valid.

This means you have rock solid assurance your program won't have database syntax errors at runtime. Basically it's just one less thing to worry about, and it's ideally suited for LLM-generated code.

newaccountman2Jul 11, 2026
Oh ok, I think I am using it wrong lol

I remember that being one of its "pros" when I was going over options with the LLM, but now, I just have a bunch of raw SQL strings in my codebase and sqlX's main use in that project, off the top of my head, is just instantiating Rust objects from the raw results with `FromRow` (it's probably doing more than I realize; I am not as connected with the code as I want to be, using LLMs to move fast to launch a couple features before revisiting a lot of the mess).

dionianJul 11, 2026
I have worked extensively with FP and non FP codebases with LLM. I find my highly type safe FP code works really really well with LLMs
threethirtytwoJul 11, 2026
You’d be surprised. It works quite well without the static guard rails. But the static guard rails do improve things but not in some extremely obvious way.
antonvsJul 11, 2026
> "At Scarf, we started doing all new API work in Python."

Start the countdown timer for how long it takes them to discover that was a mistake.

Nothing to do with Haskell, but good grief, LLMs do not in any way, shape or form save you from the deep, unfixable problems with Python.

At the very least you need all the static checking machinery like Ruff, Pyright, and hefty unit tests that take the place of typechecking if you don't want obvious failures to only show up in production.

I had this recently with an ML training pipeline, where Python is essentially forced on us. A dynamic error occurred after 17 hours of training - something that a real type system could have easily caught.

The solution that the LLM came up to prevent this in future was a complicated Enum-based system that just made me wish I could use a real programming language.

pjmlpJul 11, 2026
It is a win win situation, they get to write a new blog post about doing a Python to Rust rewrite.
notenlishJul 11, 2026
Lol
rtpgJul 11, 2026
What would be your goto for the ML training pipeline?

I have the impression that Python basically wins by default in those spaces due to the lack of many good libraries in other languages (except for, like, C++).

But curious if this is just a very outdated view of the world

IshKebabJul 11, 2026
Yeah Python seems like a bad choice. LLMs seem to write low quality Python compared to Rust, presumably because there is a lot more low quality Python in their training sets than there is for Rust.
forgotusername6Jul 11, 2026
I have heard "the poor type safety" argument from writers of strongly typed languages for many many years. Having written js and python for a large amount of my carrier I can count on one hand the number of times I've found a bug that was due to a type issue. With LLMs it has been the same pattern. They don't seem to produce issues with types.
tezzaJul 11, 2026
well i’ve come across it loads, especially 1/2) during REPL style build outs and 2/2) calling libraries and frameworks you are not yet familiar with.

perl another offender… is it a hash? is it an arrayref? over time you get it right, but by trial and error and looping. json suffers this too, arrays different from strings, different from numbers etc, but opaque until checked and liable to change

IshKebabJul 11, 2026
There's absolutely no way that's true.
sdeframondJul 11, 2026
> I can count on one hand the number of times I've found a bug that was due to a type issue.

Most bugs aren't type issues until you make them be type issues by expressing some business invariant in types.

Refactoring makes an exception not being caught the same way as before ? Type issue. Mixing up some ids ? Type issue. Etc.

Now that can also be emulated with extensive tests. But isn't that a concern for OP as well ?

zahllosJul 11, 2026
I've never done anything "serious" with haskell, just small personal projects. Mostly this is because I've found the ecosystem to be a pain - when I was trying stack stack was the thing to use but from what I can tell ghcup+cabal now work better.

If you push through that you end up with code written in a language people have used for formal proof (seL4 model is Haskell) and deployment wise a binary that +/- libraries you depend on ought to be reasonably portable.

I'm very surprised anyone would want to go the other way. Same ecosystem pain, plus you need to start shipping interpreters or containers, plus the language just doesn't really compare.

pseudohadamardJul 11, 2026
I know several people who are serious Haskell users despite, like you, using it just for small personal projects. All of them are quite some way down the autism spectrum and will casually toss around Haskell concepts that require about 30 minutes of googling by anyone else present in the conversation to try to understand. Get two or more of them talking to each other and everyone else present is more or less excluded from the conversation... and this is something they're doing just for fun, not because they're paid to do it.

It could just be a coincidence of statistics, but it does cover every Haskell user I know (needless to say, these people are much smarter than I am).

garethrowlandsJul 11, 2026
The number one hard working concept in Haskell is parameterisation. A typical Haskell concept is just a concept, not a Haskell concept.
casey2Jul 11, 2026
It makes sense, Haskell is basically just python from the code perspective. If it's faster to generate code than to compile it you might as well just keep generating til it works for your specific task.
raverbashingJul 11, 2026
My experience has been that the more type/safety checks the more chances there are of the AI getting stuck into a stupid loop

Because a lot of times it's missing the way of making the needed steps for the conversion (or it's just not obvious)

Sometimes it needs some nudging

Also this comment is a bit generic, it can also apply to cases where it's not an obvious "type check" but a redundancy that needs to exist but the AI can't get around

adrian_bJul 11, 2026
The only complaint against Haskell was about long compilation times.

I agree that short compilation times are very desirable, but I do not see why Python must be the solution for that.

I do not know whether Haskell can be compiled quickly, but from my experience, I am very certain that short compilation times are easily achievable for languages with good static type checking, especially with compilers that have different options that allow choosing between fast compilation and heavily optimized compilation.

An optimized compilation may require a much longer time than a fast compilation, but that has no relationship with the programming language used in the source text, but only with the intermediate representation used by the compiler and the target CPU ISA. Usually, if you compare the compilation times of multiple programming languages, all the compilation times with fast compilation options are much shorter than all the times with high-optimization options, so the programming language choice may be less important than the chosen compiler and its command-line options.

When you try to optimize a project by generating many variants with a LLM, I doubt that all those variants will be generated from scratch, completely independently, even if only for the reason that when using a commercial LLM the cost of a completely new variant will be much higher, by requiring many more tokens, so whenever possible it is preferable to generate other variants by just patching previous variants.

Whenever a variant is generated by editing a previous variant, incremental compilation can be used, which should be pretty much instant on modern computers.

nextaccounticJul 11, 2026
> The only complaint against Haskell was about long compilation times.

There is also this

> How do we make library docs full of copy-pastable, realistic examples, not just beautiful types?

Which is useful for humans as well as agents.

Haskell indeed has a very bad track record of documenting its libraries. For many people, just having the function signatures is documentation enough.

Rust is equally bad at compile times (if not worse) but its standards for documentation is at another level

gbaconJul 11, 2026
> For many people, just having the function signatures is documentation enough.

You make a fair point about a documentation gap. The first step is always defining the problem. Wanting to add lots of realistic examples sounds like a wish for more tutorial or beginner-friendly content. Do you see the problem differently?

On the other hand, a given pure function type only has only so many possible implementations — why tools such as djinn and MagicHaskeller exist or why Hoogle is actually useful, unlike the horror of searching for every `void (*)(const char *)` in C.

https://hackage.haskell.org/package/djinn

https://hackage.haskell.org/package/MagicHaskeller

https://hoogle.haskell.org/

From that perspective, Haskell docs tend to be more expert-friendly — perhaps a rationalization, granted — which seems ideally suited for an in-IDE model to help bridge between developer intent and typechecked code. However, this comes at the expense of putting in the reps to rewire the developer’s brain to think in functional terms and the resulting mind opening and horizon expansion to think new thoughts she wasn’t capable of even considering. In these days of LLMs, fretting over that particular opportunity cost may be thinking nostalgically about the loss of craftsmanship in fine, well-balanced buggy whips.

In the limit now, will all programming be strictly literate?

toolsliveJul 11, 2026
> Rust is equally bad at compile times

OCaml enters the room...

mbac32768Jul 11, 2026
Sounds a bit like surrender here.

There's no reason to read the code anymore.

The LLMs produce it inhumanly fast.

They can usually debug and fix problems faster than Haskell can compile the project.

Meanwhile the open source communities are in basic denial about AI, so trying to change things by making compilation faster or advancing a Haskell interpreter are going to meet with fierce resistance.

Whatever. Give up. Just ship Python.

I sympathize.

fjdjshshJul 11, 2026
The problem in Scarf's case wasn't Haskell's type system, but the long compile time for even small changes.
dnauticsJul 11, 2026
> I can't imagine using a language without a good type system

have you tried?

i use elixir and carefully watch the agents and its very seldom making typing mistakes (elixir is in-between, it's typed but only as a checker).

ultimately typing doesn't help as much because it's nonlocal information. if the system can locally infer what the shape of functions is, it's way better.

brainlessJul 11, 2026
"i use elixir and carefully watch"

- I do not watch agents, at all. Rust and Typescript. When I use Typescript only I have some guidelines so that we build the stack to be as strict and type driven as possible.

vcfJul 11, 2026
Similar for me, I don’t want to babysit agents . I’m sticking with Python for the libraries (data science ecosystem), but I find that imposing ty and a few reasonable ruff rules (imposed with pre-commit so the agent can fix things automatically) improves agent-generated code a lot.
muragekibichoJul 10, 2026
I'm not trying to be reductive but the article's a lot of words for "We're vibecoding our app now and the glorious (almost almighty) Haskell compiler is too slow for the agent to iterate it's mistakes until it gets it right."
weinzierlJul 10, 2026
This thought completely neglects the idea that Haskell probably needs significantly less compiler runs because every run catches more errors and gives more information about them.

And that is not even considering how often the agent needs to run tests to get it right.

derdiJul 10, 2026
It seems pretty clear that they do only minimal live testing during the "open a ticket, implement something, deploy it in production, all while the customer is still on the call" cycles. So your second concern is probably not relevant in this particular setting.

Regarding the first, I think you're probably right, but then again, if there is a 15-minute base cost, it's hard to amortize that through fewer incremental runs of the compiler.

(Which isn't to say that I think they are doing the right thing.)

aviaviaviJul 10, 2026
The number of compiler runs doesn't matter as much as the total elapsed time it takes to finish the task. In just about every test we ran, LLMs are faster at building in Python than Haskell.
andersmurphyJul 11, 2026
Lisp/smalltalk programmers have been going on about this tradeoff for a long time. It mattered before LLMs too. Lisp/Clojure repl allowing you to compile tiny parts of your program inside your running program is incredible for your feedback/iteration loop.

Ironically, this is also what makes them shine with LLMs, the LLM has access to the running program and can modify it while it's running to get feedback instantly.

Complex type systems are cool. But, they are not free. I say this as someone who's first programming language was Haskell.

cubefoxJul 11, 2026
> I say this as someone who's first programming language was Haskell.

Amazing. How did that happen? Is it true that functional programming is only counterintuitive because almost everyone starts out with an imperative language?

lelanthranJul 11, 2026
> The number of compiler runs doesn't matter as much as the total elapsed time it takes to finish the task. In just about every test we ran, LLMs are faster at building in Python than Haskell.

How much faster? IOW, what's the difference (in minutes/seconds, not in percentages) between vibing Haskell and vibing Python?

lenkiteJul 10, 2026
I am wondering whether next year there will be re-write of Scarf after the vibe-code degenerative collapse of their source code into un-maintainability. At some point, the LLM patch/fix cycle will devolve into straitjacket.
jimbokunJul 10, 2026
Maybe overly verbose but makes an important point.

Slow compile times should have been a deal breaker for how they impacted human coders. LLM coding just makes the problem more stark.

andersmurphyJul 11, 2026
Yeah compile times have always mattered. It's why games often have a scripting layer in lua despite the engines being C/C++.
marcosdumayJul 10, 2026
Mixed with some complaints on how the community doesn't like vibe-coding, and that if you insist on not letting AI think for you, you will be left to die in the dust of the other competitors.

The amount of certainty random people have that LLMs have already revolutionized software development seems to be directly proportional to the media awareness of the AI companies finance unsustainability.

whateveracctJul 10, 2026
Haskell Foundation member mind got cursed by wearing the CEO hat and he forgot to "avoid (success at all costs)" kek
woadwarrior01Jul 11, 2026
Granted LLMs aren't very good at the ML family of languages. Isn't vibecoding a lot safer with a typed language? Going from Haskell to Python is going from one end of the typing spectrum to the other.
matt2000Jul 10, 2026
I am increasingly wondering if we are in a post-language world in terms of development. Why would I ask an agent to write a server in anything other than the most efficient language, although efficiency can take several forms: runtime, token usage during development, and wall clock dev time (affected by slow compile times for example).

My intuition is that type-safe languages with fast compilers are the best option. Maybe Go? I personally prefer Java just due to my experience running it in production, but am not sure there's many arguments for it over Go in a greenfield application. The other candidate would be Rust, but I worry about token efficiency and tool performance, I suspect it's not worth it for the runtime improvements.

All that being said, in this article switching to Python seems like a wild choice. Relatively poor performance, no compile time checking at all. Python's big selling point was developer ergonomics, which seems largely irrelevant now.

These are all just thoughts at the moment, I should try to find some evidence one way or another.

ffreireJul 10, 2026
Language choice had less impact than people first assume even before LLMs in most software. A good engineering team produces good code in whatever language they happen to be using. In my own career I've worked in serious Java, Scala, Haskell, Javascript, PHP, and Python application stacks and I've seen plenty of good and bad examples.

I reckon language choice matters more at the edges of economic activity where a specific language feature really does make the difference in the end product, but most activity that is leveraging LLMs now is more generic enterprise SaaS software.

bbmatryoshkaJul 10, 2026
You are ignoring LLM-ergonomics, some time ago I saw benchmarks showing that popularity the language (and so more data available in training date) was strongly linked with LLM's performances, with top results with javascript and python. I don't know if a year later this is still true, but is absolutely possible
zitterbewegungJul 10, 2026
There is one simple thing you have to realize why Python is the optimal choice. You have so much training data. Python is the second most popular language on GitHub and is easy to read.
derdiJul 10, 2026
My thought reading this article was: Why write the system in any one language at all? And I don't just mean having some parts in one language and others in another language, I mean redundant implementations of the same parts. You can use an AI to rewrite parts of the system, and then throw away the old part... or you could just keep the old part.

That is: Have a Haskell base system. Have a Python "development" version on which you iterate at lightning speed. But also, in the background, moving at whatever pace it takes, have an agent running that imports all the Python development changes into the Haskell version. Have nightly builds of the Haskell version to reap its benefits (issues caught by the type system, more efficient native code). They must have continuous or nightly processes to fix bugs in the Python code anyway, there is no way that all the things they ship "while still on the call with the customer" are always tested on the full test suite and always 100% correct.

And it doesn't have to be Python/Haskell of course. The "development" version could be a (hypothetical?) interpreted Haskell. I have no idea if ghci would be useful for this. Neither do I know if the 15-minute Haskell build time is spent in the frontend (so an interpreter would have to pay that cost too) or in code generation or linking (which the interpreter wouldn't need to care about). Anyway, these are things I would think about before I did what the OP did.

crabmusketJul 11, 2026
I felt similarly. I wonder why the author is so invested in Haskell specifically becoming an AI-pilled ecosystem and community when the choice of language rounds to not mattering?

Go is the perfect language for this new world. Its development loop is fast, it has types but not too much so, it is memory safe, it is easy to deploy and it runs efficiently enough for most line of business use.

Go was originally developed specifically for a world of interchangeable hard-working juniors, which is exactly what LLMs can scale up with only your budget as the constraint.

I'm wondering what advantage a hypothetical faster-compiling-Haskell would have in that world.

jasimJul 10, 2026
I'm curious about the choice of Python, rather than TypeScript.

I find Ruby a very beautiful language, and Rails is an excellent web framework, but I need typed functions, record types and sum types.

They help not just with correctness, but also as living documentation that lets me understand AI generated code. TypeScript provides discriminated union, but not exhaustive pattern-matching, and its syntax is a bit verbose, but since I'm no longer writing most of the code myself, I can live with it.

However I can't imagine using Python or any other dynamic language going forward. There is likely good reason for you to choose it, and I'm curious to know what that is.

em-beeJul 10, 2026
python has optional types too now. if you could get the LLM to produce typed python would it be any worse than typescript?
jasimJul 10, 2026
I hadn't considered that, you are right. Though I would still prefer TS because the language is all about types; the entire ecosystem is well-typed and the type system is quite powerful (I do enjoy an occasional Omit and Pick). But it is a personal choice; as long as LLMs can generate well-typed Python, then for people who like the language it makes sense. However from the article, I got the sense that they went completely dynamic.
rpbiwer2Jul 10, 2026
Yes, because the code you (or the LLM) writes is only part of the equation; if you use third party libraries then it becomes an ecosystem problem. I'm not currently using much Python but my understanding is that the community has not yet aligned on typing nearly as well as the TS community has.
em-beeJul 10, 2026
my understanding is that the [python] community has not yet aligned on typing nearly as well as the TS community has

this is undoubtedly true.

kreyenborgiJul 10, 2026
NPM
rowanG077Jul 10, 2026
This is quite insane to me. If I compare the output of LLMs for python vs statically typed languages it's really not a good choice to go the python route. It consistently produce relatively garbage code along actually good code. My experience has that the better static typing you have the better the code becomes.

LLMs have made me move away more from python rather than into it. I'm very surprised by this experiences of the author. The article is all over the place as well. Going basically all in on Python because it is apparently better than Haskell for LLM use and than agreeing with someone that says Rust is the best.

calebkaiserJul 10, 2026
I've been a power user of LLMs for software development for a while now, and I've found two things to be true:

- The benefits of more "extreme" type systems are more accessible and valuable than ever. I have a fairly involved project built on Lean that I hope to open source this month, and it's been a joy to work in even for uses outside of mathematics.

- Readability, build time, infra complexity, and everything that affects your speed after finishing your implementation--these things now matter more than ever.

It's sort of a dual ergonomics problem, in some sense. And given that, the author's lament makes complete sense to me, especially:

"An AI-enabled Haskell ecosystem would ask different questions. How do we make Haskell easier for agents to use well? How do we get more high-quality Haskell examples into model training data? How can we scale reviews? How do we make library docs full of copy-pastable, realistic examples, not just beautiful types? How do we make project bootstrap fast? How do we make error messages more agent-friendly? How do we reduce cold build times? How do we make common industrial patterns obvious to a model that is trying to help?"

lp4v4nJul 10, 2026
I'm not a Haskell developer and I hadn't heard of this company "Scarf" before.

As much as I respect this guy who tried to work and push an alternative ecosystem, it's hard for me to shake off the impression that, rather than due to Haskell compile time, he moved to python because it's easier to find developers for it and it's the de facto scripting language for LLMs.

No problem about that, of course. Running a company is hard enough, I think that passion and idealism for a language/platform/technology out of aesthetic appreciation can only go so far and after a certain age just making money and reaching your professional objectives count more.

jimbokunJul 10, 2026
How the hell would you know his true intentions?

Fast compile times is one of the most important qualities for developer productivity. It made Haskell a non-starter for many developers even before LLM driven development took off.

yakshaving_jgtJul 11, 2026
I run my company on Haskell purely for economic reasons. Aesthetics doesn’t come into it.
domenkozarJul 10, 2026
We at Cachix have also moved on from Haskell about two years ago and I'm sure someone is going to make a comeback with a language that takes the lessons from it but starts from skratch.

We need more general purpose Elm languages in the space.

em-beeJul 10, 2026
what did you move to, and why?
domenkozarJul 10, 2026
Rust, mostly because:

- haskell exceptions and laziness are devastating for production

- too small ecosystem, had to write 10+ SDKs (now with AI that's less of an issue)

- haskell ecosystem is too fragmented due to prima donna prevalence

aviaviaviJul 10, 2026
I would love to see that happen!
jimbokunJul 10, 2026
Isn’t tgat language Rust, practically speaking?
voidhorseJul 10, 2026
"Hammers are now a very popular tool, and one can move quickly building exclusively with hammers, so we have decided to construct buildings strictly using nails, no more screws, bolts, or any other kind of fastener shall be used going forward."
pessimizerJul 11, 2026
You say this as if it were necessarily irrational.

Clothes became chain-stitched (and later lock-stitched) because machines could chain-stitch. If there were a super-efficient hammering machine, it could be better to figure out ways to use nails to replace screws in designs than to hold onto screws just for nostalgia's sake.

hunterpayneJul 11, 2026
"If there were a super-efficient hammering machine, it could be better to figure out ways to use nails to replace screws in designs than to hold onto screws just for nostalgia's sake."

How about for the sake of the bridge continuing to stand? Or is that not a good enough reason for the accountants?

cruxJul 10, 2026
I strongly agree with the premise of this article, which is why I am surprised that the author moved away from Haskell to Python.

For some time now it’s felt clear (or at least extremely) compelling that agents need fast compile times in order to be effective, especially when you’re working in parallel. But the other thing that has felt just as obvious is that agents need strong type systems and narrow guardrails in order to constrain their outputs. These two things felt clear enough to me that, like the author, I wanted to choose a language ecosystem that maximized them. There _are_ languages that both have expressive type systems _and_ fast compile times. I wonder if the author investigated any of them, before deciding that no compilation time at all was acceptable.

In my case I landed in OCaml. I think there are other options in the space—Go if you want less typing but faster compiles; Rust if you want more types but slower compiles. My mostly vibes-based evaluation landed on OCaml, and I’ve been pretty happy with the results.

UltraSaneJul 10, 2026
I've gotten best results with LLMs generating Go, Java, and C# code as they have the best combination of strong type systems and fast or no compile times.
pjmlpJul 10, 2026
Yes, and in Java/C# case, AOT compilation is also available.

I would also add Kotlin, Clojure and F#.

Scala not really as the compilation is not much better, and since the Scala 3 reboot, the ecosystem doesn't seem to be doing that well.

The market opportunity for Haskell on the JVM is gone, although they are doing cool stuff with capabilities.

em-beeJul 10, 2026
just curious, can you point to more details to what happened with scala3?
pjmlpJul 10, 2026
They introduced a new Python like syntax, and pushed to move away from the curly based syntax.

There were other breaking changes as well.

https://docs.scala-lang.org/scala3/guides/migration/compatib...

This naturally broke all the tooling.

Then you have Metals for VSCode InteliJ plugins, while the Eclipse plugin was dropped.

InteliJ plugin is much further than Metals, however there is the conflict of interests with pushing Kotlin instead.

Meanwhile most Scala shops have pivoted to also give feature parity on modern Java, and Kotlin, thus reducing the interest in using Scala in first place.

However as mentioned, they are doing cool stuff with capabilities at EPFL for Scala 3.

https://virtuslab.com/blog/scala/introduction-to-scala-3-che...

hackingonemptyJul 10, 2026
The usage stats on GitHub are declining, for example. Devs are choosing Kotlin, Rust, and Go over Scala.

IMHO there are a bunch of reasons

* Scala 3 was a Python 3-esque disruptive event

* Perception as an overly-complex kitchen-sink inclusive language

* Kotlin took up the "better Java" mantle

* Rust became attractive to devs not committed to the JVM

* Go became less sucky

* SBT is disliked and Metals was buggy and unstable (and still slow)

* Suffers from the "we won't be able to find devs" problem where Kotlin, Rust and Go don't

* A bunch of community drama drove some devs away to Rust

I say this as someone using Scala 3 with ZIO effects system and Mill build tool and thinks it is fantastic.

japgollyJul 11, 2026
There's definitely less Scala jobs on the market these days.
hunterpayneJul 11, 2026
I can't even describe how much I dislike SBT.
hunterpayneJul 11, 2026
Just to put it in perspective, most Scala programmers rejected Scala3 before it was even written. The Scala team, in their infinite wisdom with a collective 2 years of professional programming under their belt knew better. Nobody switched and Scala2 has been slowly dying with their neglect ever since.

PS The Scala team should have been fixing their type inference engine which lacked some important features and needed a better (Horn clause based) architecture. They did a complete rewrite instead.

em-beeJul 11, 2026
wait, how did the scala team end up with only 2 years of professional programming experience? did the original developers all leave?
pjmlpJul 11, 2026
I think it is a play on Scala being mostly developed at EFPL as research language and only a few on the team having worked in the industry.
dizhnJul 11, 2026
I used TS and Go mostly with LLMs and they are very good at them. Python has been fine too honestly. A surprise entry is Flutter/Dart. They are very good at it. I think it's a mixture of types, the good tooling and focused documentation.

All of these I run in a cli that has automatic LSP in it so that's a huge factor too. The agent is automatically told when there would be compile time errors as well as linter issues.

yxhuvudJul 11, 2026
I'd argue that any type system that don't support enforcing non-nil/nullability is not strong in any way and probably worse than not having any type system at all as they give a false sense of security.
eductionJul 10, 2026
>agents need strong type systems and narrow guardrails

I read the second paragraph of linked article as saying close to the opposite of that, particularly,

"the model can often avoid the mistake before the compiler ever sees the code. And as the models get better, the relative value of catching every possible issue at compile time changes."

In other words, LLMs are much less likely than humans to make dumb, fat-finger mistakes, and, when they do, are able to catch and fix them more quickly, ergo the value of type checking has fallen.

Everything in the prior sentence is, obviously, highly debatable. But it felt like part of the premise.

em-beeJul 10, 2026
i read that too, but i am highly skeptical. i wish the author would investigate that claim and provide some actual examples substantiating it.
pmontraJul 11, 2026
My experience with Claude and Ruby, Python, Javascript is similar: it's pretty good at finding the array of strings that was passed to a method instead of an array of integers. Think about record ids coming from a JSON API call. Or the single value instead of an array. I don't remember which Python XML parser is fond of returning one or the other according to the cardinality of the sub elements. Anyway, not only it writes the code to handle those cases but it traces the code and it finds the bugs. So type checking at coding time and who cares about writing the type annotations. They would be probably good to speed up the code at runtime but none of my customers use them and none of them is concerned about the current response time of their systems.
aviaviaviJul 10, 2026
Main factors were (roughly in order):

- None of us are experts in Rust, and we're all solid at Python.

- Rust felt like an under-correction for what we wanted (get all friction in front of the LLM out of the way).

- Our high-performance stuff is not being migrated at this time (Scarf Gateway), so we're just talking about basic CRUD backends here. Basically any language will work.

bencedJul 11, 2026
Python has so many footguns for server work and the world's worst typing system. It sounds like Golang is perfect for your use-case
whateveracctJul 11, 2026
Golang has to compile the world iirc, so it'll need more and more time and resources as the slop grows in size.

Whereas Python just interprets and gets off to the races.

Feels like we had this discussion years ago as humans..the false promise of dynamic languages.

hunterpayneJul 11, 2026
Python is preferred because Python programmers are cheaper than other languages. Not because of any sort of technical advantages. Its literally the worse performing programming language in popular use. And it uses invisible characters in its syntax. Truly, it is the VHS of our industry.
whateveracctJul 11, 2026
good point

it's a shame scarf is struggling so much they are pinching pennies :/

YZFJul 11, 2026
Python just interprets and blows up in production more like it ;) Also so slow. But bad Golang is full of `any` and turns into a Python in disguise.
whateveracctJul 11, 2026
agreed. i just use haskell for everything because i'm not a wuss
bkovacevJul 11, 2026
What is exactly slow when building APIs in Python and compared to what? :)
phrotomaJul 11, 2026
True that an interpreted language has a leg up on any compiled language in the arena of compile time, but worth noting that one of Go's primary design goals was improving compile times of massive code bases. Google was drowning under the weight of compiling huge C++ codebases and Go was the response to that (among other things).
typesanitizerJul 11, 2026
Go compiles things at package-level granularity. You only need to recompile your reverse dependencies on making changes. Also there's build caching available out-of-the-box, as well as some support for test caching.
timcobbJul 11, 2026
> None of us are experts in Rust, and we're all solid at Python.

you don't need to be, you can learn Rust or whatever way-better-than Python language as you use it with an LLM! it's an amazing process.

camkegoJul 11, 2026
You might not like Microsoft but they did a video on why they re-wrote the last version of the Typescript compiler in Go. Basically, because of LLMs. It's worth viewing even if you don't decide to go with Go.
sroerickJul 11, 2026
OCaml works incredibly well with LLMs.
phillc73Jul 11, 2026
Which models have you found work best with OCaml?

I also went through quite a process to select a language to work with LLMs[1] before settling on OCaml.

I am not unhappy with the choice and find it works quite well, with relevant skills loaded, but I am always interested in others’ experience and understanding what they’ve discovered works well.

[1] https://news.ycombinator.com/item?id=48105850

Foobar8568Jul 11, 2026
LLM are string happy instead of using ADT with ocaml. That was my main pain point with it. Otherwise fairly happy, I would feel C#/.net core would be the best overall in term of language/platform.
TheGoddessInariJul 11, 2026
Personally been experimenting in Lean 4. LLMs understand it, can be given simple rules to improve it. Typing is strong, proofs are solid, and it compiles quickly.

On the contrary, for a small rust project, I had to clean out 180gb of cargo nonsense from the last ~3 days worth of compiles on a single, narrowly focused topic branch.

The library situation might be funky, but I'm also learning Lean 4 by hand. The tooling & lsp integration is lovely.

aryonocoJul 11, 2026
Very interesting that I followed a very similar reasoning and settled on F#. Tells me that our process must have been very similar.
eggyJul 11, 2026
Why did you choose F# over OCaml? I am in the same boat and evaluating both. Mainly systems programming, applications, etc.
59nadirJul 11, 2026
Both of these are near useless for systems programming and predictable behavior when caring about performance.
LyngbakrJul 11, 2026
Jane Street uses OCaml in a domain where performance matters.*

*https://signalsandthreads.com/performance-engineering-on-har...

bbkaneJul 11, 2026
Jane Street has unlimited engineers and money to do this.

At least from the sidelines, it looks like they've built/forked most parts of the OCaml ecosystem to make it work (OxCaml, Dune was built by then, custom profilers, custom networking hardware, etc).

Of course a lot of their work is open source and can be used, but I wouldn't assume that it would be worth the effort to do something similar with OCaml yourself. Maybe it is! LLMs go brrr and all that.

cosmic_quantaJul 10, 2026
Note that Scarf is not moving away from Haskell for performance-sensitive applications [0], which was the immediate question I had reading this.

[0]: https://discourse.haskell.org/t/after-7-years-in-production-...

HizonnerJul 10, 2026
I am absolutely baffled at the idea that LLMs mean you need less automated verification of correctness.
classifiedJul 10, 2026
Wow, another bunch of people who give up engineering to satisfy their addiction to speed.
whateveracctJul 10, 2026
it's sad, isn't it?

if my CEO wrote this article, I'd quit [1] in an instant

[1] "quietly" while i found gig+1. oh and the private out-of-band engineering gossip and trash talk would surely be hilarious

AlexeyBelovJul 11, 2026
Yeah, I don't get it. There are so many real-world bottlenecks that it doesn't matter if you can edit the code 10x faster. It could even be beneficial to tactially slow down some parts of your SDLC.
cosmic_quantaJul 10, 2026
For what it's worth, I've been using Haskell in production at Bitnomial, a financial exchange, and LLMs + Haskell is an extremely productive combo.

Since Opus 4.6, LLMs have been pretty clever at using fancy types with libraries like Servant and Beam. The expressiveness of the types, combined with feedback from the compiler, means that agents converge quickly to something that works. I don't think I've noticed agents having to run the compiler so often that compilation speed is an issue.

aviaviaviJul 10, 2026
I'd be very curious to hear your take if you gave another language a proper try for comparison with the same tools. I think you'll be as surprised as we were.
nh2Jul 11, 2026
Hey, we have a 10 year old Haskell/Python/C++/TypeScript/Nix codebase, and use all of them regularly.

Haskell compiles slowly, but we have not found that to significantly inhibit AI-supported dev so far. We use ghci with `-fobject-code`, and our largest leaf module (10k lines of webserver request handlers) takes 8 seconds to `:reload`. To run stuff in it, the agent pipes `:reload`, or other invocations, into `ghci`.

Working on parts parts that are early in the module chain, such as our Prelude, makes the whole-project `:reload` take 50 seconds. Much of that could be avoided if we didn't suffer from the TH recompilation problem (https://gist.github.com/nh2/14e653bcbdc7f40042da3755539e554a). Originally I made a small GHC patch to hack that out (what this conservative recompilation protects from cannot happen in our project), which made the reload much faster, but the logic was changed in recent GHC so that doesn't work anymore.

In C++, we have some individual files (and thus compilation units) that take 45 seconds to compile.

Python is of course the fastest to (build+run). However, Python also has some problems with repeated runs: Once you have many imports, just starting the program (e.g. `--help`) takes ~2 seconds resolving imports. Do `import pytorch`, add another 2 seconds. For repeated runs, this can be a pain; Haskell and C++ are much faster for that, so they win when you don't have to change the code but repeatedly use already-compiled tools in a different way.

In all 3 languages, getting things to typecheck is very fast, because the agent directly reads the vscode LSP typechecking errors which are < 1s feedback. Claude Opus 4.6-4.8 understand all 3 languages very well.

I agree that GHC devs should focus most of their efforts on compile speed, and real-world pain solving. Some parts of that are indeed being done (e.g. newest GHC can write bytecode to disk to make the above workflow much faster, and codegen is by far the slowest part of compilation). But I think the focus should be even more on that. I consider most important and unsolved:

    * solving Generics being slow to compile, especially for types with many constructors
    * solving deriving classes being slow to compile
    * solving TemplateHaskell causing too much recompilation
    * doing staged compilation,
      so that the next module can typecheck as soon as its imports are typechecked,
      as opposed to waiting that codegen is done;
      this unlocks a large amount of parallel work availability
All of these have open GHC tickets that I think should be the highest focus.

Other real-world production things are being solved quite nicely currently:

    * The new Haskell debugger
    * Much better stacktraces
    * Much better runtime introspection to debug runtime hangs etc
I get your general point that if iteration speed (as in change code + run, 100s of times a day) is your highest value, Python does quite well. We intentionally chose Python for the part of the codebase that's relatively simple data importing but from 50 different sources, count growing adding new sources all the time, and need just quickly iterate on each until we got it.

But I find it would not be a great language for the other parts. Its concurrency story is bad, its interpreter is very slow and immediately disqualifies Python when you need to do e.g. a line of code for every 1000 Bytes (say for streaming small data chunks), typing is very useful but bolted-on and not always correct.

Things where Haskell remains best-in-class is anything nontrivial-webservers, I/O, program correctness, the main "general purpose" programming, refactoring and long-term maintainability.

nh2Jul 11, 2026
Another side remark:

LLMs removed some of the difficulty of Haskell, e.g. some interesting ideas to make things safer with sophisticated types or mechanisms like TemplateHaskell are now MUCH easier to implement in a few minutes. Also Haskell's general stance of breaking backwards compat in fundamental places if it's needed to make the language better, thus causing moderate amounds of upgrade grind, completely evaporated as a drawback because LLMs are extremely good at fixing type errors to bring code up to date with the latest changes.

The LLMs are very good at explaining Haskell compile errors.

Learning Haskell and maintaining projects in it is now easier than ever.

pjmlpJul 10, 2026
I was expecting yet another moving from Haskell into Rust article, instead they went to Python.

Who cares about performance.

robertlagrantJul 10, 2026
I like this article, but I would take some issue with the concept of the percentage of time taken up being a major issue.

If you go from taking 2 days to write some code and 20 minutes to type check (which does seem long, don't get me wrong, but still) to 10 minutes to prompt some code and 20 minutes to type check, that percentage increase to me isn't enough to justify switching.

You're still almost 2 days ahead, and converting those 20 minutes to 20 seconds are not going to make you ship a feature appreciably faster. But those types stand strong and I don't believe they can yet be replaced by an LLM believing they're correct.

Having said that, I also think that Haskell should massively speed things up. Having strong types if nothing else should surely produce some amazing type-checking speed wins.

romanivJul 10, 2026
Languages designers will have to make a choice whether to continue to design for humans or for big slop machines. The design goals are not compatible. This is obvious. I don't understand how anyone can miss such an obvious point.

Another obvious point is that an industry that runs on code slop will stagnate in terms of language an human tooling design.

pjmlpJul 10, 2026
Robots need formal specification languages, to tame non deterministic compilers.
rkrzrJul 10, 2026
This is a good post. AI has changed the programming language trade-offs and, as someone running a company that uses both Haskell and Python, I hope that Haskell can adapt to this new era.

I would like to add one additional observation, since we have been using both Haskell and Python in production for a long time:

Haskell excels at platform work, while Python excels at product work.

Our infrastructure teams work in Haskell (and also Rust nowadays), while our product teams work in Python. This gives us the best of both worlds (in my opinion): fast and rock-solid infrastructure on the platform side, and fast development speed and quick iteration cycles on the product side.

This setup has worked well for years for us, but it remains to be seen how and if this is going to change as well in the new AI era.

derdiJul 10, 2026
> The type system caught real bugs.

> The model can often avoid the mistake before the compiler ever sees the code.

> The type safety we gave up hasn’t been noticeable in any concrete way yet [...]

> Type safety can be a huge advantage for LLM-generated code if the compiler is helping the agent converge quickly.

Well, good to have this question cleared up once and for all :-)

typesafeJJul 10, 2026
Very surprised about this decision. I use strict languages much more with LLMs and they improve quality a lot. Working on a big python codebase is very painful with an LLM.
reinitctxoffsetJul 10, 2026
I'm internally dogfooding my take on the stack that makes all these problems go away.

Everything sort of exists, but it's this heinous zero documentation, high pain tolerance thing: buck2 and RBE with NativeLink and hooking that up to action runners and it needs to all work in a container or on nix or in a deb and on MacOS, you hand roll the auth and the certs and where do your compilers come from, can it do NVIDIA, can it do mobile.

Problem is switching off Haskell doesn't help for long: the agents proliferate and you're back where you started with more bugs. So I've been sucking it up and getting all this shit one click and it works. This is good enough for my use, and if the Scarf folks want a solution and are willing to work with a garage band startup, I'd be open to doing a closed alpha. I have a buck2 where you write the rules in Haskell (if you even need to change the prelude, it ships with a WASM that isn't coupled to fbcode), and the Nix cache/substitutor is backed by NativeLink so it scales to anything and it speaks all the protocols correctly and with a verified supply chain.

I'm not even really sure this will become a product, I just need it, but I sort of suspect others will need it too. If there's interest I'll put up a landing page with an email sign up thing.

zeendoJul 10, 2026
I am surprised by this take, honestly.

We're a Haskell shop (and have been for over 10 years now) and are finding agentic development with Haskell to work pretty damn well.

Cold compile times in Haskell are painful indeed. Our development practices don't really cause us to do that much - even with agents.

It's unclear to me if the development practices at Scarf that cause them to hit this pain often are worth it if it means giving up Haskell because the compile times are too bad. Maybe they are, but I don't think so.

tonyarklesJul 10, 2026
Speaking as someone who has tried Haskell but hasn’t ever really gotten into it, but spends all day with a C++ codebase that also has long cold-compile times… I think the author of the post said they’re using git worktrees to be able to have multiple agents working on different things at the same time without stepping on each others’ toes. I’ve started experimenting with that myself and it’s great in a lot of ways but by having a separate source tree, it does trigger the cold compile problem. Two agents compiling the code in separate worktrees are working on entirely separate builds (great!) but that means there’s no shared compilation cache between them (not great). Is that something that’s tripped you? Have you found a good solution?
pianopatrickJul 11, 2026
Just spit balling: could you have the agent pre warm the cache as part of your workflow? Like at the start of working on the code have the agent run a compile in the background. That way when the agent is ready to "really" compile there is a warm cache
tonyarklesJul 11, 2026
Probably not a bad idea for just making sure that you’re starting from a buildable tree anyway!
markasoftwareJul 11, 2026
Bazel maintains a system-wide cache that fixes this. At $current_employer a truly cold build (rm - rf the system cache) is 10 minutes or so. In a new worktree with a warm system cache it's under 60 seconds (still needs to build the worktree specific analysis cache). A fully warmed build is 10 seconds. Additionally there's no lock on that system wide build cache.

For this reason alone I want to like Bazel. But at the same time it has like half a dozen caches for different purposes and doesn't feel generally elegant. It saddens me that (a) cargo can't do this afaik and (b) its hard to package Bazel packages under nix. I'm not sure what other system has a shared unlocked cache.

bbkaneJul 11, 2026
The Cargo folks actually have caching funded for a bit (though I'm not sure how well it interacts with worktrees)! See https://rust-commercial-network.github.io/rcn/funding-direct...
tristenharrJul 10, 2026
This is the silliest take I’ve ever read. Strong type systems are an AI’s best friend.
kreyenborgiJul 10, 2026
Even without considering vibecoding, compile time and compiler/lsp memory usage are my main concerns with Haskell. In fact, I'd say they're even more of an issue if you're going without LLM's since they affect human beings ;)
sn9Jul 10, 2026
OCaml is such an obvious solution to their problem that I'm shocked it wasn't even mentioned. You get fast compile times without sacrificing type safety.
sroerickJul 11, 2026
I posted this above but honestly OCaml makes vibe coding so nice. I went back to go after a few months with OCaml and it was deeply frustrating
subversiontacoJul 10, 2026
Every time I see a post like this it somehow turns into a conversation about AI. Are there any studies on this? How much better are typed languages for LLMs. I would expect the amount of data and scaling laws to have more of an effect on an LLMs coding capabilities than the language itself.
tonyarklesJul 10, 2026
I mean, in this particular case one of the biggest pain points they’re talking about are just straight up build times. An LLM that can produce a patch in 5 minutes and then has to wait 15 minutes for a build… to then put together another 1 minute patch and wait another 15 minutes for a build… that’s not ever going to be able to compete with Python where there’s no build time at all.
jbrittonJul 11, 2026
I write a ton of Python code. Modifying code without static types is difficult and error prone. If a function needs a new argument, all the callers have to pass it and all of their callers recursively. Maybe the calling function is just a function pointer that has been passed around and not searchable. I love Python for small tasks and tasks that are not critical if they fail.
atomicnumber3Jul 11, 2026
I also write a lot of python code. Ported 2 companies from python 2 to 3 too (idk why that keeps happening to me).

Lots of modern (...3+) python code uses type hints and a type checker. It can be as strict as you'd like it to be, which is exactly how I like it. It's what pulled me away from ruby.

Meanwhile, static languages are too often a giant pain in the ass, and in return for writing a lot of annoying code, you get in return guarantees that only really apply within your process's memory. And in a microservices world... you're actually realistically using the protobuf type system. Which generates just fine for python. And then "internally" you can use python's type checking where it helps, and if it doesn't help, then for that bit of the code, simply don't use it (and write "true" python).

I also find that a HUGE problem in the world is that programmers just. can't. help. themselves. They LOVE to over-define. LOVE IT. It's a siren's song!! Static type systems are a trap for the part of our brain that loves to architect. One of my favorite things about python is that it helps programmers _let go_. Not everything needs to be an interface. It's python. Everything is already an interface. Now just write the code without all the distracting 20 layers of indirection. And if we ever need one more, it's python - it's practically already there. Just make a new type, put @property on some methods, and you're good.

Obviously there are times I'd not use python. I could foresee myself writing Rust if I had to do code where correctness was of utmost importance (like, crypto, or embedded software for a medical device where someone's ventilator is hooked up to it, or similar). But if nobody's going to die (so... medical and cryptography...) then I'm using python almost no matter what I'm doing. And I'll use numpy or write a C module if I actually end up needing true CPU-bound performance for something.

jbrittonJul 11, 2026
Well said.
faangguyindiaJul 11, 2026
I am writing couple of State machines and DSL in Haskell.

Haskell is great, once you write code, chance of certain kind of bugs appearing is very low.

Biggest problem i've is i develop on Apple Silicon and can't cross compile to x84 linux which is most common deploy platform for servers

Compare this is to Go, which is what i use for almost everything else, cross compile, copy to server and there you go! So simple.

this causes a lot of pain and suffering and slow development loop in Haskell.

I'd use Haskell for more things if someone solves this issue.

Please haskell community, come up with a way to solve this issue. It wouldn't be a problem if i've to install a JVM like we've for Java.

jasonjmcgheeJul 11, 2026
Hey Avi - didn't know you were an HNer fun to see you / your co on here :)
hedgehogJul 11, 2026
I don't have the experience, how high are Haskell compile times such that a switch like this is worth it? I have some experience with generated Python, Rust, and TypeScript, and I have not found that compile time is enough of a concern that it would offset additional safety of a stronger type system. Like some of the siblings I'm now starting to do experiments with Lean and other tools to get even stronger assurance about system behavior.
yakshaving_jgtJul 11, 2026
Long compile times can be a problem. It’s also a problem that can be managed. I think this is overstated in the article.
Barrin92Jul 11, 2026
I'm honestly baffled that someone who has been writing software for so long puts so much emphasis on code generation as a meaningful metric. As Fred Brooks taught us, conceptual unity, not lines of code is the most important metric for the long term health of a software project.

It's interesting in particular because the argument of the article has at its core nothing to do with coding agents:

"so far, we haven’t lost much in the switch. The type safety we gave up hasn’t been noticeable in any concrete way yet, especially considering our test coverage has never been better."

people said the exact same thing when they moved from Haskell to Python or to JavaScript before the latest tech. Tests, tests, tests, and faster development cycles is just the language of the Agile people who have been advocating for this for decades. The people who didn't buy it never did so because the claims about development speed were wrong, they didn't buy it because they had a fundamentally different outlook about what matters in a codebase over years. I'm interested to see how this will look in three years rather than three weeks. If you're so seduced by the idea that shipping next months feature faster is so important I honestly don't know why you ever chose Haskell in the first place.

iLemmingJul 11, 2026
Oh wow, Haskell to Python. Interesting. They must have really wanted to preserve cascaded dependency headaches.

___

Please don't let your kernel panic, I'm being sarcastic. You never know the level of emotional attachment some HN people have to their tooling...

whateveracctJul 11, 2026
cabal hell isn't even a real thing anymore.....
iLemmingJul 11, 2026
I know that. Bumping GHC can still be relatively painful. Some language stacks are meaningfully easier on dependencies (not you Python), but can give you some other headaches (yes, you Python, damn you). Every PL in one way or another has some warts and ugly parts.

It seems the job of a senior software engineer these days is to make fun of programming languages on HN pointing out their flaws, while simultaneously keeping an eye, waiting on agents doing "thinking".

whateveracctJul 11, 2026
whoa buddy, i'm a senior eng but i don't wait on agents. ew!

i could probably do my job and get passing (or better) perf reviews using nothing but fundamental-mode and the compiler.

ljwallJul 11, 2026
I only use Haskell in hobby projects outside of work but somewhat regularly run into problems with package bounds causing conflicts or forcing some project on to an older GHC than I'd like. It's not cabal hell since its confined to one project and not system wide, but it's definitely a pain point.
whateveracctJul 11, 2026
so Go has the same issues in my experience. but instead of "solver failed" you get compilation errors. I definitely had to fork a nontrivial amount of Go libraries to maintain my startup's backend.

"solver failed" is in theory a better error. it fails faster and is unambiguous. maybe because it's weird it is scarier? idk

the main issue is managing PVP bounds is a little hard to keep correct. but cabal also lets you "allow-newer" for duct tape.

tangenterJul 11, 2026
LLMs are heavily trained on Python.
prmoustacheJul 11, 2026
It remains to be seen if agentic development really provide an advantage, especially when you see the extraordinary fall in reliability of products and infra managed by early adopters. Development time is hardly the bottleneck in my company for example.

Also I assume the cost of development skyrocketed so much over the months that our company started implementing drastic cost reductiom measures everywhere that seem to mitigate any improvement we've had.

purpleideaJul 11, 2026
Haskell definitely needs to improve a lot of things, but moving to python is obviously a mistake for most cases. Golang is probably the best language for LLM things, it's got reasonably strong types, compiles very fast, and is simple. Much nicer to work with than Rust for example. But these days most code should probably be golang or rust if you're not building a webui.
threethirtytwoJul 11, 2026
Typescript is the best for AI along with Python. Purely because there’s so much training on it. The LLMs are better at typescript.

Also typescript is a better overall language than golang. More expressive types. Golang wins in performance and simplicity and raw ugliness.

kazinatorJul 11, 2026
I feel there is something missing here. The narrative here suggests that the author's LLMs are generating perfect Haskell code that just needs to be rubber stamped by the compiler for execution. But, oh, that takes too long.

I'm skeptical; I would think that the problem would actually be that mistakes in a large body of Haskell code would be difficult to fix: that massaging the generated slop into compiling ranges from unpleasantly time consuming to intractable.

Might the author be hiding the honest statement of the problem: that he would rather move fast and break things as a slop artist, but the guard rails are too rigid in Haskell?

adamddev1Jul 11, 2026
The author talks about how Haskell needs to catch up to stay relevant in "the AI era."

> That means taking AI seriously as a first-class user of the ecosystem.

Honestly for me any time a language or a tool markets itself as "for the AI era" or takes agents seriously as first class users, I run. It's a bad smell for me.

I'm happy that there are things like Haskell that are still focussed on correctness and sanity, and not pandering to the AI psychosis driven on by the market.

I am really disturbed by this ideological framing of "it's the AI era now" "we have to let the agents run" "speed, speed, speed" "if you don't learn to engineer with random garbage, you will be left behind!!"

Some of us will need to leave the cult of the empire of AI and live in caves like the desert fathers, committed to actually crafting correct things.

youre-wrong3Jul 11, 2026
> I run. It's a bad smell for me.

The smell follows you but atleast we don’t have to smell it any more. Thank you.

pietmichalJul 11, 2026
I wonder what will happen when LLM providers stop operating at loss. The whole claim of us being in AI era falls flat after realising that.
jordiburgosJul 11, 2026
Finally...
jiehongJul 11, 2026
That's a very fair point, and Rust shares this fundamental issue as well.

That's where one better appreciate the work being done in Zig to get incremental compilation in milliseconds.

The choice of Python is quite interesting, and a big swing in the other direction.

sdeframondJul 11, 2026
If loop time is a concern, I am surprised the author does not mention tests. Is it still worth it to wait for your test suite to run when an LLM can get it right quick ?

Edit: I dont quite buy that argument, in case it was not clear.

Edit2: oh, is it specifically about incremental compile time? In which case I understand that tests can be run piece-wise quick indeed.

thyrsusJul 11, 2026
The article makes a convincing argument that Haskell compilation is too slow for the fast code generation of AI. But python?

I have yet to experience a RHEL major version change that did not blow up all my tiny simplistic python scripts. I see the following options for using python: * run inside the container it was developed in * build your own python interpreter and environment and libraries and never use python pieces from the OS (i.e., act like a container without using one) * keep different versions of the code for different OS versions and use AI to rewrite all the code for the new OS version

Start to consider third party dependencies, and none of those feels tractable without an AI assist.

I've dabbled in C device driver code and kernel version differences were my only problem, not C. My perl scripts never break. My bash scripts rarely break. My dabbling in erlang didn't suffer from language version differences. My little elisp hasn't broken. Only python has inflicted this level of version pain. I have a colleague who says java has the same version pain as python, and from what I've seen from Jenkins maintenance he may be right, but I don't have colleagues who want to read java code, so I haven't written my own.

ngrillyJul 11, 2026
uv is solving these problems for the kind of things Scarf is developing.
efromvtJul 11, 2026
never use system python, always use virtual envs. (a bad answer, but agents do remove the setup boilerplate). UV does relatively completely solve this but it's a big dependency to take so understand why people don't rely on it
thatguymikeJul 11, 2026
Very interesting! I honestly would have expected the opposite: I was optimistic about strongly functional languages in the age of AI. The more modular and side-effect-free your code is, the easier it should be to constrain changes, catch slop, and reduce LLMisms like spooky hacks-at-a-distance.

It looks like the issues are in the compiler and documentation so hopefully it’s fixable… I write in Python every day but I do miss smarter languages and I hope AI doesn’t fully obliterate them.

jdw64Jul 11, 2026
The development workflow is changing, and Haskell as a language doesn't fit that new workflow anymore. The traditional strong type system basically forced you to spend a long time thinking before writing code. The upside is that this makes the code more logical and robust. But it's the exact opposite of the AI loop. It's not that the type system is wrong—it's that the toolchain that comes with a strong type system has itself become a bottleneck.

With AI coding emerging, a single person can now churn out 100,000 or 200,000 lines. And realistically, from my experience, once you go past 40,000 lines, it's hard to memorize everything. So what do you do? Human coding shifts toward writing tests and gates, and once you feel comfortable that things are safe, you add more features.

AI coding takes this to an even more extreme level. Learning Haskell is great for learning domain modeling—I learned domain modeling through Haskell myself. But now that AI has become genuinely useful, it seems like a fundamental shift in workflow is happening.

Realistically, for commercial competitiveness, the domain of code black boxes is getting larger. The number of lines a single person has to manage is increasing, but their cognitive limits haven't changed. Even the amount of background knowledge required keeps growing.

In that sense, I agree with the author's point. It's not that Python is a better language than Haskell, so people switched—it's that Python has almost no build-up process and it serves as the standard interface for AI models.

The value of a language as a product doesn't come from the compiler's excellence. It comes from its users.

Avi Press's article ultimately reflects the reality that if you can't stay ahead throughout the entire lifecycle, you'll fall behind your competitors.

Maybe I'm just echoing my own thoughts, but it's reassuring to see that a well-known programmer thinks similarly to me.

tpoacherJul 11, 2026
> Now there is a third place: code generation time. The model can often avoid the mistake before the compiler ever sees the code.

This is doing a lot of heavy lifting here. How do you even know a mistake has been "avoided", and safely, for that matter? The kinds of mistakes the AI will miss are the worst kind: subtle logical mistakes, buried inconspicuously within boilerplate code, hard to detect or reason about, until one day you wake up to find that your database has been replaced by a rickroll video.

Also, it's odd that they moved from Haskell to completely untyped python ... python may be no Haskell when it comes to type safety, but typing+mypy/mypyc goes a very long way.

jwrJul 11, 2026
Interesting. The major factor seems to be the latency of change-compile-test cycle.

I wonder if one of the reasons I've been getting such excellent results from LLMs with Clojure could be that they can immediately try things out in the running REPL. Rebuilding my entire application from scratch takes minutes, while connecting to a running system through nREPL and compiling single functions or namespaces takes less than a second.

alexbezhanJul 11, 2026
I find the need for type systems is less important now. and thats me saying this after 15 years of coding in Java, Scala, Kotlin, Typescript.

Now I am using Elixir and incredibly surprised by how little I need static types. They are useful, but less needed now.

Never could believe I would say that. But I'm the most productive I ever been.

I get bugs of course, but they are related to queues lengths, retries, api errors, memory usage, performance, ... Bugs related to incompatible types are rare.

VerdexJul 11, 2026
This isn't a great comparison.

Im not that familiar with elixir, but erlang is hands down the best dynamic language to build systems in. It feels like they made only right decisions. I can only assume that elixir has made improvements on that.

Meanwhile java and kotlin have the least useful types I've encountered in my career. Scala has some pretty powerful stuff, but it's like the c++ of powerful types. The ergonomics aren't great. Finally, typescript has a lot of impressive typing constructs but it really falls down on the runtime side (because javascript).

The real comparison to make would be erlang/elixir vs rust or ocaml.

zelphirkaltJul 11, 2026
You probably have built very solid concepts/ideas about what types are in the program and how to name things, so that they make sense, and all other things that lead to a program being useful and easy to read, over the course of those 15 years. The situation might not be the same for more junior devs.

But also Elixir's paradigm is not the same as lets say some PHP slinging or JS. It encourages a stricter functional style, that already makes for better code than what many people produce in languages like JS and PHP, or Python.

rr808Jul 11, 2026
Scala was a dead end. Kotlin an obsolete workaround. Java though is now awesome, esp if you can ignore Spring. Should be more popular in the tech world.
seanwilsonJul 11, 2026
> The important metric: how long does your entire development feedback cycle take, and what portion of that time is spent waiting on your compiler?

> So far, we haven’t lost much in the switch. The type safety we gave up hasn’t been noticeable in any concrete way yet, especially considering our test coverage has never been better.

Moving to Python means you'll have quicker compile times but now you'll need a bigger test suite which will take longer to run to get feedback after code edits? In TypeScript, you can compile and execute without waiting on type checking, an option like that would help?

yakshaving_jgtJul 11, 2026
I’ve been running my company on Haskell for a similar length of time.

Long compile times can be an issue, but it’s an issue that can be managed.

Would I scrap Haskell in favour of Python, now in the age of agentic coding?

No. No I would not.

nesarkvechnepJul 11, 2026
The whole article feels like a rationalisation for vibe coding your product from now on.
catlifeonmarsJul 11, 2026
The justification in TFA smell like premature optimization. A nominal bottleneck is just that-nominal. It’s a good thing to keep in your back pocket but you generally don’t want to expend extra effort optimizing something until you have to.

I suspect that the cost of long compilation times (preLLM even) was actually quite high and the author is discounting/excluding those other factors and focusing on LLM feedback loops primarily as their justification.

As an aside short feedback loops are important, but the article ignores one major reason why: humans learn most effectively when the time between action and feedback is reduced because the contents of our working memory degrades over time (take the explanation with a grain of salt). LLM has no such restriction, so the only thing that matters is that the codegen can keep up with the demands from the actual product.

lgrapenthinJul 11, 2026
tldr; they decided to sacrifice quality for quantity via outsourcing their programming, and find Python more suitable for this.

Which it always has been, whether outsourcing to cheap "talent" overseas, or now a subscription service text generator.