112 comments

[ 3.2 ms ] story [ 90.0 ms ] thread
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.
> 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.

You should read the article before replying.
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.

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.

It's about the feedback loop being so slow. Agents often compile and run tests to verify their work
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.

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
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.
> "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.

Unfixable errors? Why unfixable? Python is Turing complete. I can see difficult to fix, but not unfixable. LLMs lower the bar to refactoring code mistakes.
So is excel.

I actually enjoy python and astral tools a lot, but I think you are grasping for air here.

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.
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.

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.
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

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.

The problem in Scarf's case wasn't Haskell's type system, but the long compile time for even small changes.
> 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.

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."
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.

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.

Haskell Foundation member mind got cursed by wearing the CEO hat and he forgot to "avoid (success at all costs)" kek
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.
I was puzzled by this article at first, but when you put it that way it makes more sense. The author also had a presentation awhile back about why Haskell is a terrible language for startups to adopt. I imagine that in the current venture environment vibe coding is being pushed heavily by investors since companies are effectively in an arms race where feature development cost is moving towards zero and investors don't care about individual companies because they have a portfolio of bets.
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.

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.

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.

At some point, (programming) languages themselves will become vestigal abstractions.
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.

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.

(comment deleted)
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?"

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.

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.

I run my company on Haskell purely for economic reasons. Aesthetics doesn’t come into it.
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.

Isn’t tgat language Rust, practically speaking?
"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."
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.

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.

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.
>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.

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.

Using a frontier model you can combine it writing high-quality Rust and educate you in the process. You guys were too scared, needlessly.

But as others said: if Haskell was not giving you too much in terms of excellent typing system then maybe going for a PL with a much faster compiler like Golang would have been best for you.

Java/Kotlin would have given you what you needed, and more (better observability, performance, etc.)
OCaml works incredibly well with LLMs.
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.

Very interesting that I followed a very similar reasoning and settled on F#. Tells me that our process must have been very similar.
Same, the article is really solid but then they choose to migrate to… Python?

This feels like someone giving a great commencement speech, then proceeding to pull out a gun and shoot himself in the foot as the final act.

I am absolutely baffled at the idea that LLMs mean you need less automated verification of correctness.
Wow, another bunch of people who give up engineering to satisfy their addiction to speed.
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.

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

Who cares about performance.

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.

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.

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.

> 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 :-)

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.
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.

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.

> 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.

It not that it didn't work at all, so much as that it worked much better in other languages when we compared side-to-side. It's possible we had dev practices that could have been modified further to suit Haskell better (we had been doing that for years already), but increasingly I want the toolchain to adapt to us, not the other way around.

This is the silliest take I’ve ever read. Strong type systems are an AI’s best friend.
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 ;)