Author here: not only have I heard of LLMs but I built a domain-specific programming language for prompt engineering: https://github.com/Gabriella439/grace
Author here: it's not even clear that agents can reliably permute their training data (I'm not saying that it's impossible or never happens but that it's not something we can take for granted as a reliable feature of agentic coding).
As I mentioned in one of the footnotes in the post:
> People often tell me "you would get better results if you generated code in a more mainstream language rather than Haskell" to which I reply: if the agent has difficulty generating Haskell code then that suggests agents aren't capable of reliably generalizing beyond their training data.
If an agent can't consistently apply concepts learned in one language to generate code in another language, then that calls into question how good they are at reliably permuting the training dataset in the way you just suggested.
Your argument is far too dependent on observations made about the model's ability with Haskell, which is irrelevant. The concepts in Haskell are totally different to almost any other language - you can't easily "generalize" from an imperative strict language like basically everything people really use to a lazy pure FP language that uses monads for IO like Haskell. The underlying concepts themselves are different and Haskell has never been mainstream enough for models to get good at it.
Pick a good model, let it choose its own tools and then re-evaluate.
Why is Haskell irrelevant to the argument that LLMs can't reliably permute programming knowledge from one language to another? In fact, the purity of the language and dearth of training data seems like the perfect test case to see whether concepts found in more mainstream languages are actually understood.
Because human programmers routinely fail to do that too. Haskell is an obscure language that came out of academic research. Several of the core semantics (like lazyness by default) didn't get adopted anywhere else and are only found in Haskell.
> if the agent has difficulty generating Haskell code then that suggests agents aren't capable of reliably generalizing beyond their training data.
doesn't that apply to flesh-and-bone developers? ask someone who's only working in python to implement their current project in haskell and I'm not so sure you'll get very satisfying results.
> doesn't that apply to flesh-and-bone developers?
No, it does not. If you have a developer that knows C++, Java, Haskell, etc. and you ask that developer to re-implement something from one language to another the result will be good. That is because a developer knows how to generalize from one language (e.g. C++) and then write something concrete in the other (e.g. Haskell).
One language in the same category to another in the same category, yes. "Category" here being something roughly like "scripting, compiled imperative, functional". However my experience is that if you want to translate to another category and the target developer has no experience in it, you can expect very bad results. C++ to Haskell is among the most pessimal such translations. You end up with the writing X in Y problem.
Your argument fails where it equates someone who only codes in one language to an LLM who is usually trained in many languages.
In my experience, a software engineer knows how to program and has experience in multiple languages. Someone with that level of experience tends to pick up new languages very quickly because they can apply the same abstract concepts and algorithms.
If an LLM that has a similar (or broader) data set of languages cannot generalise to an unknown language, then it stands to reason that it is indeed only capable of reproducing what’s already in its training data.
The hard bit of programming has never been knowing the symbols to tell the computer what to do. It is more difficult to use a completely unknown language, sure, but the paradigms and problem solving approaches are identical and thats the actual work, not writing the correct words.
Saying that the paradigms of Python and Haskell are the same makes it sound like you don’t know either or both of those languages. They are not just syntactically different. The paradigms literally are different. Python is a high level duck typed oo scripting language and Haskell is a non-oo strongly typed functional programming language. They’re extremely far apart.
They are different, but on some fundamental level when you're writing code you're expressing an idea and it is still the same. The same way photograph and drawing of a cat are obviously different and they're made in vastly different ways, but still they're representations of a cat. It's all lambda calculus, turing machines, ram machines, combinator logic, posts' dominoes etc., etc. in the end.
They’re both turing complete, which make them equivalent.
Code is a description of a solution, which can be executed by a computer. You have the inputs and the outputs (we usually split the former into arguments amd environment, and we split the latter into side effects and return values). Python and Haskell are just different towers of abstraction built on the same computation land. The code may not be the same, but the relation between inputs and outputs does not change if they solve the same problem.
Other people have replied but to clarify my point, while two languages may operate with a focus on two seperate paradigms, the actual paradigms do not vary. OOP is still OOP whatever language you use, same for functional et al. Sure some languages are geared towards being used in certain ways, some very much so, but if you know the actual ways the language is largely irrelevant.
> The paradigms literally are different. […] They’re extremely far apart.
And yet, you can write pure-functional thunked streams in Python (and have the static type-checker enforce strong type checking), and high-level duck-typed OO with runtime polymorphism in Haskell.
The hardest part is getting a proper sum type going in Python, but ducktyping comes to the rescue. You can write `MyType = ConstructA | ConstructB | ConstructC` where each ConstructX type has a field like `discriminant: Literal[MyTypeDiscrim.A]`, but that's messy. (Technically, you can use the type itself as a discriminant, but that means you have to worry about subclasses; you can fix that by introducing an invariance constraint, or by forbidding subclasses….) It shouldn't be too hard to write a library to deal with this nicely, but I haven't found one. (https://pypi.org/project/pydantic-discriminated/ isn't quite the same thing, and its comparison table claims that everything else is worse.)
I am very sceptical mainstream languages will be better. I have seen plenty of bad Python from LLMs. Even with simple CRUD apps and when provided with detailed instructions.
The tool now supports local models. In particular, you can pass an alternative base URL for both embeddings and completions so if you can serve a local model over an OpenAI-compatible API (e.g. using LM Studio) then you can point the tool to that.
Author here: yeah, this is a good point and something I think about even outside the context of agentic coding.
I've also tinkered with this idea myself in the context of prompt engineering with my Grace Browser project (https://trygrace.dev/), which converts code to an equivalent dynamic web form live within your browser.
I do think it's useful to remember that code is not the end goal and is itself just another mediated interface to the actual goal: the product your building. However, I think even if you cut code out of the picture the chat interface is still not necessarily the right interface for building a product. A great example of how to build a non-chat interface to product building (predating the AI boom) is Bret Victor's Inventing on Principle talk (https://www.youtube.com/watch?v=PUv66718DII) and there might be ways we can refresh the ideas in that talk for the AI era (although I still don't have any specific thoughts along those lines yet).
Totally agree about the chat interface. I like to say it’s “infinitely powerful and infinitely confusing.” A dangerous combination. And, arguing with myself, I think it’s fair to say the code is AN object of our attention, if not THE object. A common metaphor being applied to agentic coding is the invention of power tools. If AI is the drill, and the goal is a house, then the code is the framing.
I did not use AI to generate my blog's content nor layout.
Also, the reason my blog is named "Haskell for all" is because I originally created my blog a long time ago to try to make Haskell more accessible to people and counter the elitist tendencies.
I agree. Firing is at least more honest (or there's a lawsuit if it isn't). Being pushed out sucks. I know because it's happening to me right now for bullshit reasons (the complaint is that my throughput is inconsistent but yet my average throughput is better than the other dev of my level on the team, and I'm involved in more above and beyond work). Being pushed out is very stressful and has negative mental and physical effects, especially if you have specific disabilities (I do).
Exactly.
I usually don't stick around when a team enters that phase, but sometimes it takes a 6-12 months to exit.
I've been on teams where management very clearly tries to do a good team/bad team split.
This looks like hiring some space cadets to build the "strategic solution" that will magically fix every problem with the existing system (despite being managed by the same senior management).
The existing team is told to just keep the lights on / the new thing is going to be so much better / just give it another year or five.
There's not a lot of upside to staying around because you either end up fired at the end if the space cadets succeed, or if the space cadets fail you end up holding the bag of rescuing them in X years post strategic platform failure. And sometimes a secret third thing - the company being run this poorly ends up having to do RIFs and you end up fired randomly anyway.
Author here. It is true that one of my goals in writing that post was to discourage people from jumping on the NeoHaskell train, but a larger goal was to educate people on what NeoHaskell actually was because there were a LOT of misconceptions floating around that led to confusion (and that confusion in turn amplified the drama because people were reading things into NeoHaskell that were not actually true).
That's actually correct versioning in Haskell. The Haskell ecosystem uses a different versioning convention from other ecosystems where the first two components of the version number signal breaking changes. For more details, see: https://pvp.haskell.org/