Skip to content

Instantly share code, notes, and snippets.

@graninas
Last active March 18, 2024 14:57
  • Star 249 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save graninas/22ab535d2913311e47a742c70f1d2f2b to your computer and use it in GitHub Desktop.
What killed Haskell, could kill Rust, too

At the beginning of 2030, I found this essay in my archives. From what I know today, I think it was very insightful at the moment of writing. And I feel it should be published because it can teach us, Rust developers, how to prevent that sad story from happening again.


What killed Haskell, could kill Rust, too

What killed Haskell, could kill Rust, too. Why would I even mention Haskell in this context? Well, Haskell and Rust are deeply related. Not because Rust is Haskell without HKTs. (Some of you know what that means, and the rest of you will wonder for a very long time). Much of the style of Rust is similar in many ways to the style of Haskell. In some sense Rust is a reincarnation of Haskell, with a little bit of C-ish like syntax, a very small amount.

Is Haskell dead?

There was a time when Haskell was the language to watch. During the late 2000s through the 2010s, Haskell was the language everybody wished they could program in, but nobody did, except for maybe a few people. There were some pretty impressive projects that were done in Haskell. There were massive financial projects done. There were payroll projects that were written in. But perhaps the most impressive from the point of view of a purely functional language like Haskell was Pandoc which had a Haskell core. It slapped in the face the whole notion “Haskell is too slow”, or “Haskell just can’t do real things”. Of course it can, and it did.

What happened? Why did Haskell suddenly, pretty suddenly just stop? It’s certainly not alive now. No one is contemplating major projects in Haskell any longer. Who is a GHC Haskell programmer here? I presume there are one or two people with their hands in the air. The GHC Haskell dialect has kinda fallen into an academic language. No one was really considering anything serious.

Haskell in its time was at the forefront of functional programming. It was the language that kind of characterized or epitomized what FP was really about. There were other languages that were functional, but they were only sort of functional. And of course, I’m talking about languages like Scala, or JavaScript. Those were the two major competitors during the same mid 2000s. Scala, JavaScript, and eventually, Golang, and C++ were followers. Haskell led them. These languages learned a lot from Haskell. Anybody doing Scala now knows that the syntax of the for-comprehension and many of the libraries, come directly from the Haskell world.

Haskell ruled.

It ruled in a way that no other language could have at that time. It ruled technically. There was a productivity which is measured at perhaps a factor of five. A team of developers could get an application written and shipped five times faster than a Scala application, or a C++ application. A factor of five is fairly significant in our world.

Haskell also ruled in ways that were just beginning to grasp. How many of you are using monads? But I’m using monads in JavaScript, and I have a little bit of a monads in Rust. In Go, I can do amazing things with monads. The thing about that is that the Haskell people had that in mid 2000s. There were monads and algebraic data types that were immensely powerful long before most of us even thought about a monad.

Haskell ruled in a whole bunch of interesting ways and yet it died. What killed it?

I’m gonna use a word here, and I don’t want you to take the word the wrong way. The wrong way you could take the word is “evil”, and the other way you could take the word is “ignorant”. But it’s not quite even “ignorant”. The word I’m gonna use is “arrogance”.

There was an arrogance in the Haskell community. Not the evil kind, but the kind that told them that they were somehow better. That the tools they were using were somehow better. That the things they were doing were somehow better. There was the arrogance of those people who believed that victory was inevitable. This was not the slapping your face “you, stupid fool golang programmers” kind of arrogance, although there was plenty of that, too. Instead, it was a kind of arrogance of power. Because the Haskell people were writing a pretty powerful code, they did have a tiger by the tail. It was a powerful compiler, it was a powerful language, and they knew they could work miracles.

And yet, that wasn’t enough. Something insidious, something subtle happened. It caused their separation, they set aside the rest of the industry. The people outside the community who were writing everyday programs began to look at the corner of the eye where the Haskell people were doing: “Emm… Haskell people don’t seem to like us very much, I don’t think we’re gonna like them”.

Some of you might remember the Reddit discussions in the mid 2000s. A bunch of people were there. And they were talking about cool math things there. In those talks, they often were snickering about other languages like Go. It wasn’t anything significant, it wasn’t anything evil, they were just snickering: “He-he-he, mainstream people, ha!”. But I was a mainstream golang guy at that time! I didn’t like that. And I’ve been dealing with language wars in the next couple of years. And I said to them at that time “Do we really want to have language wars on Reddit?”. And the interesting thing about it was not about what they were snickering about, because they probably had a right to do that. What was interesting about is my reaction. My reaction was defensive. My reaction was “Well, you guys, go ahead and do your Haskell thing, but I’m the one who gets real work done.”

That’s the interesting division that got set up at the time. And it was fairly pervasive. There was an attitude among the Haskell community, and again, it’s not an evil attitude, not one that was born out of ill will. But there was an attitude that said “You know, our tools are so good, our language is so good, we don’t need to follow the rules. We can do something else. We don’t have to talk to other people. We don’t have to do the other kinds of programs.” Haskell people didn’t want to do the regular kinds of programs. They didn’t want to have to deal with the corporate database. They didn’t want to have to deal with the horrible schema that had evolved twenty years. It was just distasteful. And they found ways instead to do things like using category theory, and dependent types. They’ve built a wall around themselves, and they’ve chosen to live in a technological bubble. Isolated from the evils of the outside world.

I’m going to define a word here. It’s a word you all know. And this definition is just one of many. You can find other definitions of this word if you like. The word is “professionalism”. And I’m going to define it as “The discipline of the wielding of power”. We have a certain amount of power in our tools, in our languages. But it requires a discipline to wield that power. And it’s not just a discipline in the use of the tool, it’s a discipline in a relationship to the community at large. It is a discipline that says: yes, it is a powerful tool, but powerful tools kill very quickly. And they kill in surprising ways, so we’re going to be careful. And we’re not going to denigrate people who are a little bit less willing to use our smart powerful tools.

Let us redefine “progress” to mean: “Just because we can do a thing it does not necessarily follow that we must do that thing”.

So what killed Haskell is the parochialism, the inability to address the needs of the Enterprise.

Haskell was a stellar performer in certain constraint circumstances but it was limited in its ability or rather in a desire of its users to address the general problems of the Enterprise. There was a certain purity among those people. They didn’t want to step outside and so lead themselves in the soil of real work. There was an “us versus them” feeling of uncleanliness, and those of us on the other side of that boundary felt it palpably. Parochialism is an “Hey you” attitude. It’s a way of putting a big banner on the screen saying “Hey you, I’m gonna do my way and screw the rest of you”. It’s a way to say “We are great in our little domain, and the rest of the world can go to hell”.

What is my save?

I want to save Rust and all other wonderful works that are going on in this community from that same demise. Frankly, I don’t think it’s anywhere near going down that route. First of all, the community is I think more dynamic and larger, and I believe that there is no longer the antithesis “us versus them”. Those of us who are “strong C++ hormonal programmers” have relented. And everybody is looking around and thinking: “You know, there might be something to this Rust stuff.” But still, what is it? What can save Rust from going down the same path that Haskell went?

I’d name 3 things:

The first one is discipline. Discipline specifically in documentation. A technical discipline that can keep Lord Cunningham’s problem from happening. It is writing documentation. And by god, it is a hard thing to do. You just want to write the code. But you should write that damn documentation. I mean all of you have found how hard it is to sit down and say “I’m going to write a good documentation so that others could use my work easily”.

The professionalism of humility is something that may prevent the demise, the same kind of demise that occurred for Haskell. The “us versus them” attitude. No, I know there have been some funny advertisements like “Mac versus PC” thing. “I’m Rails, and I’m Java”. And I don’t think there is any harm in it unless you take it too seriously. Unless you build the wall. Or unless they build the wall in response.

And the last thing would be acceptance of solving the “dirty” problems. Solving the problems of the horrible schema. And we're gonna have to sit down and say “No, we’ll deal with that”. If we’re going to survive in the end, we have to address problems that everybody has. Otherwise someone else will address those problems.

Remember the fate of probably the most powerful and influential language of the 2000s. The language that was at the start of pure functional paradigm, the language that influenced so much of what we’re currently doing. The fate of that language was near oblivion. And the people who used it and loved it had to jump to Scala for a living, and it nearly killed them.

We have great tools in the Rust language. We could kill it by making a mess, we could kill it by being arrogant about it, we could kill it by ignoring the Enterprise. I suggest that we not follow that route.


As one might have guessed, this is not an essay. It's a transcript of the following talk by R. Martin with some substitutions made (SmallTalk -> Haskell, Ruby -> Rust, and others). You are free to make any conclusions from this.

What killed Smalltalk, could kill Ruby, too

@educob
Copy link

educob commented Nov 20, 2022

I have actually changed my mind about Rust.
The frist book I read about it was really bad (at least for me) and I got a very negative view about Rust.
But then I studied a second book and now I understood the why of all "weird" stuff and it makes more sense.
Anyway a difficult language.

@zerosign
Copy link

zerosign commented Dec 16, 2022

hmm, Could you clarify a bit about ignoring Enterprise in here ? I though some of the "Enterprise" already using Rust in solving system programming focused problems and I think Haskell are also aren't being killed in here, it's just much more focused ? cmiiw

@virtualritz
Copy link

I think nothing killed Haskell. It is still a great language for the stuff people used it for (and what it was meant to be used for). It just doesn't dominate the news as much any more.

One of Rust's aims and one of the reasons I have little fear it will have a similar destiny as the one the author fears for (popularity mainly?) is that it was (among many other things) meant to be a possible replacement for C/C++.

That's why data in Rust can be mutable. That's why Rust is not garbage collected. That's why there is no built-in async runtime. That's why you have have rather low-level stuff like std::simd in the standard library.
Certain applications are just not feasible for a language when performance is a constraint and you do not have such features.

The aims are simply different and there a lot of code that is written in C/C++ that can not be written in Haskell if low-level control over runtime behavior is a constraint. But it can be written in Rust.

@dc0d
Copy link

dc0d commented Dec 16, 2022

Seconded! And while I agree arrogance is the drive that caused this historical phenomenon, it is not the reason. First, we need to replace "killed" with "died away" in the context of this comment. Haskell died away for the same reason Perl died away. It stopped being relevant. When was the last time that you heard about Perl 6? I saw a similar phenomenon among some Erlang studios that moved to Java. Their reasoning was Erlang is excellent, but we have a hard time hiring. But we would rather die than write any Elixir. That's why we move to Java. I think the most intense form of this kind of pride appeared in the Lisp community - from the beginning to "Clojure is not a real Lisp." We can observe a similar pattern in the history of Go. Zealots fought generics all over the place, and they have finally incorporated generics into the language (I am not talking about the timing itself. Maybe the core team needed this time to develop a good design). In each case, a significant market portion was lost to wasteful squabbles.

We can not deal with arrogance - or other counterproductive behaviors in humans - by fighting them. Instead, we should focus on the question, "How can rust be made more relevant?" Instead of fighting things out of our control, we can demand results. That's what the industry cares about.

At the same time, the disruptions caused by arrogance affect our personal lives as software developers. How many hours could we spend with our loved ones instead of ugly incidents in ungodly hours if we could benefit from better tools and languages? How much less cognitive load would we have? How much less burn-out would we experience? I do not think these people or the industry care much about this aspect - in some companies, they have started to look into this, to be fair.

@virtualritz
Copy link

virtualritz commented Dec 21, 2022

@dc0d Arrogance/being stuck with one tool (or language) is a very good point.

I found the Rust communtiy very welcoming. I never had these "use Rust or don't bother" moments on the resp. Discords which is were most of my experience with the community is rooted. The level of support there is outstanding. Some of the best Rust people on Stackoverflow just hang out there and help.
I remember when I was struggling with subtyping/variance and later exposing C callbacks as closures in my nsi crate which was a project that was over my head at the time (i.e. exactly what you should work on when learning a new language, IMHO), people on those Discords gave hours of their time explaining stuff to me.

I also worked a lot on Rust wrappers for existing C/C++ libs and not rarely Rust folks suggested changing the original FFI (i.e. writing C/C++ code and opening a PR) instead of trying to work around a limitation of that FFI in the Rust wrapper API or the Rewrite It In Rust pattern.
I found that very humble, down to Earth and refreshing.

It is one of many reasons why I felt welcome in that community and possibly an important one in the context of how Rust attracts people with the right attitude that will help this languange not face a similar problem as the ones you described.

@dc0d
Copy link

dc0d commented Dec 22, 2022

@virtualritz The subject of the conversation is the "potential" trap that 'rust' - the language, not the community - could fall into. Not a statement about rust (the language).

I'm new to rust, and it is only recently that I started using it. So, I'm not qualified to make a statement about the rust community. My brief encounter with the community ranged from 'rust is not Java/OOP' - the fact is that the founder of OOP, Alan Kay, believes Java is not OOP - to some real help with a not-so-straight-forward case. Which I'm grateful for. And I've heard lots of positive things about the rust community, and I am sure there is lots of good stuff I'll see if I stick around.

@liamzee
Copy link

liamzee commented Dec 26, 2022

The problem with applying this to Haskell is that the motto "Avoid success at all costs" isn't a joke, but representative of a certain period in Haskell's development.

Haskell was intended as a language for research into lazy functional programming languages. Success meant that you ended up with too many users who'd complain about every breaking change you dumped in.

The question with Haskell is whether or not Haskell actually wants to succeed, now that it's somewhat outmoded as a research language (Idris, Agda, dependent types, etc). If Haskell wants to succeed, parts of the culture have to change in order to make it more accessible to new users, as well as more suitable for production use. But that's walking away from its raison d'etre as (primarily) a research language, which is why you see all this tension.

===

In either case, I doubt certain senior Haskellers care; as mentioned elsewhere, Lennart Augustsson and Simon Peyton-Jones are working on Verse, a functional logic language with lenient evaluation, Richard Eisenberg is working at Jane Street on OCaml, and Idris is a splinter of Haskell, admittedly better than Haskell except for libraries, laziness, and type inference.

Either Haskell makes up its mind that it wants to survive, or it can choose to join the dustbin of history with Smalltalk. Due to the existence of post-Haskell languages, such as Verse (production-oriented), Rust (fundamentally imperative, but with Haskell-like type systems), and Idris, is it such a bad thing if Haskell doesn't want to survive?

@yuanweixin
Copy link

yuanweixin commented Mar 9, 2023

I was googling "rust haskell" since I am dabbling in Rust and see that the trait system really resemble typeclasses in Haskell. And to my surprise I found the OP's post (posted just 2 days ago!).

I first learned about Rust from a coworker ~2014, who used to be a C/C++ dev. That was before 1.0 was released, and he was excited about the memory safe properties. And now, having had some work experience with C++ under my belt, I can definitely say that the Rust tooling is miles ahead vs C++ tooling. On top of taking away a lot of the footguns of C++,
the Rust compiler error messages feel super friendly, and the standard tools (clippy, cargo) are very well thought out. You can tell it's designed by people who had worked on large software projects and encountered real-world issues, suffered real pain such as horrible compiler messages, lack of linting tool, or lack of a package manager. Getting these non-language pieces right on the get-go means the ecosystem can grow and new users start out happy and stay. For real world use, it is probably 20% language and 80% ergonomics of tooling. I think Rust delivers on the ergonomics. And the language itself isn't bad either. As a new user I feel "taken care of".

For any language to survive and get to escape velocity, corporate sponsorship is almost always necessary. Rust's affiliation with Mozilla, then the big tech companies in the Rust foundation, definitely lends legitimacy to the language and puts it on the table for adoption by teams. The greenlighting of Rust use in parts of the kernel tree is another push toward legitimacy, that puts it on the table for teams shopping around for an efficient language.

Then you have to contrast the runtime characters of Haskell vs Rust. Haskell has GC, and the performance characteristics is not very predictable due to default laziness. Rust doesn't use GC, uses RAII like C++, and can handle low level stuff well. So people who are looking to maximize their hw would have less hesitation picking Rust.

I worked at a F# shop for a few years, and there were a few Haskellers there. One of the early engineers was definitely one, because he defined Prelude and his own Just/Nothing, along with a bunch of functions. Another guy loved to talk about how he could write some code in a few lines of Haskell, but I think he got into Idris as the language came out. Anyways, the reason I brought up F# is because, it too had its moment in the sun, but even as an official Microsoft language, it is not popular. It is always competing with C#, and tbh, C# is pretty expressive already, so unless the decision makers at a shop are true FP believers, they will go with C#. C# also work out of box with things like Unity, whereas F# doesn't. Once that F# shop was acquired, the F# stuff got converted into Java/JVM stuff (and along with that came a ton of mediocre people and code). With a major corporate user gone, there's less word-of-mouth marketing for F#, and it just feels super niche these days. I can make the same point about Ocaml: it keeps its industry spotlight because Jane Street uses it heavily.

The point I am trying to make bringing up F# and Ocaml is that, functional programming is cool and all, but in the industry it is not used in most places. I am not saying it isn't used, but just stating the fact that very few places use FP languages, and even less places use FP languages exclusively. Most programmers are not trained/wired to think in FP style, because they were brought up with C/Java/whatever imperative language of the time. So, wrt to contrasting Rust and Haskell, I think Rust has a better chance of survival because it is an imperative language, and that alone grant it much more mindshare. A lot more people will pause and at least consider it as a candidate.

@ssokolow
Copy link

Before I saw the part about it being a substitution of a talk about Smalltalk and Ruby, I was honestly thinking "I'm not saying that Rust can rest on its laurels, but this is oversimplifying what limited Haskell's potential for growth".

Seeing that it was originally about Smalltalk and Ruby makes a lot more sense for how the comparisons were drawn.

Among other things, Haskell is, to some extent, "just another garbage-collected language (and GCs are solitary creatures)", while Rust is not only the first contender for the niche that C and C++ have held for so long that's getting significant traction, it has a vibrant ecosystem of crates for memory-safely building compiled extensions for other languages, like PyO3, Neon, Helix, etc.

That hurts Haskell's competitiveness and, like a disease that weakens the immune system, makes it more vulnerable to people dismissing it because they see having to code in a pure functional style as too big a cost for too little benefit... especially when you also bring in the Blub paradox. (As boats said, "pure functional programming is an ingenious trick to show you can code without mutation, but Rust is an even cleverer trick to show you can just have mutation.")

...though, given how the market received things like like F# and Scala, I'm not going to count Haskell's pure functional nature as strongly against it as a lot of people probably would.

Yes, Rust's borrow checker can be very painful for people who have trouble breaking out of that OOP "graph of references" mindset, but Haskell is a pure functional language without a particularly unique value proposition above and beyond "stronger compile-time guarantees".

Haskell is desirable for allowing more type-driven programming, but so is Rust and things like Serde and clap don't require you to code in a pure functional style.

...and Haskell has exceptions and space leaks to worry about. (I see the lack of maintained alternative to Rustig or findpanics (i.e. something cargo-geiger-like, but for panics) and LLVM's inability to surface the information rustc needs to make optimization regressions a compile-time error as Rust's two biggest shortcomings.)

While avoiding getting its community's friendly, helpful culture Eternal September'd and being careful to not make C++-ish complexifying mistakes while evolving async are definitely threats to be taken seriously, Rust has already picked up enough mindshare and built enough ecosystem that it'll be hard for alternatives to compete in the "modern replacement for C and C++" niche.

That's actually a big part of why I bounced off both Haskell and Go. Aside from finding Haskell's currying-centric syntax and dearth of structure-communicating punctuation (e.g. parens and braces) unnerving (I can't remember if I'd already had the shine wear off on CoffeeScript by that point) and Go unacceptably boilerplate-heavy and lacking in metaprogramming support (, neither has a strong story for memory-safe FFI with Python.

(And now that I'm using Rust, it's a reason to prioritize retiring my last PHP codebase... that, if you do use ext-php-rs to expose PHP bindings for your Rust module, you can't just import my_rust_rewrite_with_stronger_guarantees into a lot of shared hosting setups.)

However, if I had to pick a single thing that differentiates Rust from Haskell aside from the FFI friendliness, it'd have to be "research first" vs. "fearless upgrades". That's the number-one reason I'm rewriting Python projects with no FFI of note and no need for greater performance in Rust. As No Boilerplate said in Stop writing Rust, "They're not abandoned; they're done."

Do I think Rust needs to be careful not to get cocky or complacent? Hell yeah. Do I think the comparison isn't as good as Smalltalk vs. Ruby was? Also yes.

@ssokolow
Copy link

I would agree with some commenters here about Go being highly arrogant. It stems largely from Rob Pike being a complete asshole

I'm always reminded of this quote:

Syntax highlighting is juvenile. When I was a child, I was taught arithmetic using colored rods (http://en.wikipedia.org/wiki/Cuisenaire_rods). I grew up and today I use monochromatic numerals.

-- Rob Pike in response to a request for syntax highlighting in the Go playground @ https://groups.google.com/g/golang-nuts/c/hJHCAaiL0so/m/kG3BHV6QFfIJ

@AlohaHenry
Copy link

I think IRC is the one of the typical arrogance XD

@dengyunsheng250
Copy link

agree with it.

@edmondop
Copy link

If Java wasn't killed by EJB, I don't see what can kill Haskell to be honest

@Stridsvagn69420
Copy link

I think the 3 aspects you mentioned are just common sense for programming in general, like don't start stupid language wars and keep things organzied and documented.

And I also don't think Haskell is dead, even if I personally haven't used it yet. There are still projects, be it tiny or large, that use Haskell.
I haven't done anything in it yet, because either other languages were better for the job or I was (and still am) confused by the entire Monad and Functional Programming thing. I'd love to see someone explaining this to me as if I'm five, with pratctical examples.

@hkinke
Copy link

hkinke commented Jun 27, 2023

@Stridsvagn69420 If you come from OOP, you must absolutely change your way of thinking. Data are immutable, function can be a parameter or a return value, and you will often use recursivity to solve problems. Nowadays, most languages implement lambda and/or match expression (C++, Java, Python, Rust, PHP). Monads are like interfaces (as in Java or C#) or traits (as in Rust). A data to be used as Monad, must implement three methods: return, (>>=), and (>>). I recommend to desugar do notation, it is just nest calls. Many languages try to implement their own version of Monad Maybe like Rust (Result and Option), C++ (std::optional). That is very restrictive because you can create your own Monad by implementing the Monad class (interface or trait for other language).

SCALA and OCAML try to mix both functional and object oriented paradigms. The programmer chooses when to use functional or object oriented paradigms. I think F# is a bastard of OCAML. SCALA tries to mimic do notation with for statement, but it is not as powerful as do notation of Haskell.

When you know functional programming, just desugar Haskell notations.

@ssokolow
Copy link

ssokolow commented Jun 27, 2023

Many languages try to implement their own version of Monad Maybe like Rust (Result and Option), C++ (std::optional). That is very restrictive because you can create your own Monad by implementing the Monad class (interface or trait for other language).

Bear in mind that Rust's limitations with regard to monads and do notation are partly due to issues Haskell dodges by having a garbage collector instead of a borrow checker. Just like with how static/compile-time type systems are more limiting for how you can implement things than dynamic/run-time typing, compile-time garbage collection (i.e. ownership and borrowing) imposes greater limitations than run-time garbage collection if you refuse to take the C++ approach of just blindly assuming the code to be correct when it can't be determined for certain.

...that said, I don't know what C++'s excuse is for std::optional.

@bapcyk
Copy link

bapcyk commented Jul 4, 2023

@Stridsvagn69420 If you come from OOP, you must absolutely change your way of thinking. Data are immutable, function can be a parameter or a return value, and you will often use recursivity to solve problems

A function as a parameter or a return value was introduced in OOP (Smalltalk, 1969-1972). Data immutability is available in any programming language and paradigm. But good news: in most languages (including most functional languages) you may modify data in place, in Haskell - no, where you just have to hope for the optimization performed by the compiler.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment