Why exactly I want Boring Haskell to happen

By Artyom Kazak aka @availablegreen
January 9, 2021


🧱 This post is written in Brick β€” a platform for writing pretty public notes, which I co-founded. Using Brick has significantly increased how much I write. If you try it out, I'd love to hear feedback on Twitter or at artyom@brick.do.


Intro

I have already talked about all of this on Twitter, but here is a summary write-up.

My working hypothesis right now is that Haskell should be split into "Haskell" and "Boring Haskell".

Note that I am proposing something more radical than what is usually meant by "Boring Haskell". Eventually I want the languages to diverge completely β€” with a forked compiler, ecosystem, subreddits, etc.

Let me elaborate.

I.

Haskell was created as a single language for a) research, b) teaching, and c) production. (See Haskell Report, "Goals".)

I think this goal should be narrowed down.

In particular, and to make the disagreement as evident as possible, I see a lot of people pushing for "increasing Haskell's adoption in the industry". I don't think it's a particularly worthwhile goal.

In my opinion, Haskell brings the most value as a testbed for figuring out how to marry advanced type systems and "production" β€” I don't think there are other languages that achieve this goal as well as Haskell does, and this is the irreplaceable bit about Haskell. By focusing on this specific goal, perhaps we would make progress there faster.

I think the other good bits about Haskell are not irreplaceable at all:

  • Depending on the topic, Haskell is either an alright teaching language, or even a mediocre one.
  • Haskell is not the state-of-the-art testbed for advanced type systems β€” I believe it has been surpassed by other languages (Agda, Idris, maybe Lean and F*).
  • Haskell is a good choice for some industries and a poor choice for other industries, but I doubt there is a single industry where it is irreplaceable (or even merely a clear winner). Haskell has great refactor-ability, for instance, but if you treat it as a part of the "maintainability" effort, you suddenly have to factor things like "lack of tooling" into the equation β€” and then Haskell might not be the most maintainable language anymore.

Interestingly, "bring advanced type systems into production" is not a goal that I care about personally. However, I suspect it's important enough that keeping it going would be worth it, and Haskell is a big player on this scene, and so keeping Haskell going is worth it.

This is the assumption I rest my thinking on β€” that we should optimize for "marrying research with production" above all else. Why exactly would splitting Haskell help us focus on this goal?

II.

As Evgeny Poberezkin pointed out, there are three camps in the Haskell community. The camps can be summarized as "production + maintainability", "production + correctness", and "research". His comment is worth reading in full:

There seems to be a split in the community into two (or even three) camps:

  • the first is led by @snoyberg, that has a very strong focus on [Haskell] being a reliable tool for production code, and I should say I am using the stack (not just the "stack") it advocates - Reader pattern, unliftio (but not rio), etc. But to me this camp is taking it way too far - almost nobody came to Haskell with the desire to write "boring Haskell", many people I know chose Haskell because it allows to express type invariants in a wider range of scenarios than other languages. The top values for this camp are "reliability" and "approachability" - that is, be able to write production code that is highly maintainable by a wider group of engineers thanks to its approachability.
  • the second group is a growing number of commercial users who care much less about "approachability", and much more about "rigor" - they have very high expectations of the correctness and reliability of the software systems they develop, and do rigorous modelling in types. Galois would be a prime example, but there is also a growing number of financial and communication sector companies who have very high expectations about software reliability that can be only achieved via type-driven / algebra-driven design approaches. For these users a wider range of scenarios expressible as type invariants helps them achieve their goals better.
  • the third group is "research" - a strong focus on Haskell being a research playground for advanced type systems, and you, Simon, etc. seem to be here. This camp is super important, but unless it will see creating commercial and society value as a very important priority it risks losing industry support from both camps.

In a nutshell, I am worried that the first camp might win.

If it wins, the second and third camps might disperse. This is why I would like "Boring Haskell" to appear. Not because I myself want Boring Haskell, but because the first camp β€” including me β€” would flock away.

(I hoped Eta would become Boring Haskell, and thought being JVM-only was a brilliant move, but Eta seems to be dead.)

The camp that needs a good, teachable, reliable production tool, would probably have an easier life with Boring Haskell. A shared understanding of "we are making a language for such-and-such purposes" would make it easier to decide on new language features. As the simplest example β€” perhaps various quality-of-life tweaks like -XTrailingCommas would not be discussed to death for a year.

The camp that does research would also probably have an easier life with all the Boring Haskell folks leaving. Examples:

  • Bringing dependent types to Haskell is a hard task with many steps. Some of those steps have been blocked for more than a year (see the intro of the "Support ergonomic dependent types" proposal). Imagine how hard it is to create something, when you have to fight, for years, even for small steps. It's a wonder Richard Eisenberg has not given up yet.
  • Linear types took four years β€” I am not sure, but I think this is more than it took Edwin Brady to write Idris 2.

This leaves the middle camp β€” and they are essential, because without them the "production + correctness" equation would devolve into "correctness". If the first camp leaves, the overall effort put into GHC and the boring bits of the ecosystem will likely decrease. If it decreases too much, the middle camp might not be able to afford using Haskell anymore.

This is the biggest reason I am not sure splitting Haskell is a good idea after all. But there are other reasons, too:

  • What if I'm mistaken and the camps actually don't hinder each other's goals much? E.g. here's a Reddit comment about the slow rollout of linear types being possibly explainable by other reasons.
  • What if the goal of marrying research and production would be better accomplished by Haskell dying altogether? It's easier to learn from an experience when it's over, and so perhaps we'd be better off if an entirely new language emerged.
  • What if other languages are genuinely so bad that Haskell should be kept alive at all costs? (Very unlikely but possible.)
  • The biggest obstacles in the way of Dependent Haskell etc might not come from the first camp, but from the middle camp (e.g. @yav works at Galois). Hmmmmmm.
  • Since I am not involved with Dependent Haskell research or other kinds of research, it's possible that this plan is going to be much more dangerous to the research side (that I'm not involved with) than to the production side (that I am involved with). It might be much better to split off a "Research Haskell", that would explicitly aim to get to dependent types etc faster, rather than split off a "Boring Haskell".

Overall I'm not sure one way or another. But I'd like to see someone try anyway.

Objections

But isn't splitting a community always always a bad thing?

I don't think so.

Having different communities, in general, is an effective way to explore a bigger chunk of the design space that would be possible to explore with a single community β€” if only because different communities have different norms/paradigms/values.

You can possibly explore a chunk of the design space faster if you have more people on board (and even that is questionable!). However, at some point the boost you get from the community size will plateau out. You can't ever explore the full design space if you only adhere to a single set of values, and that's why we need competing sets of values.

Why not use e.g. Scala if you want a production language?

One of Scala's goals seems to be researching how to marry functional and object-oriented programming. Some people are not interested in that.

See also: the top of Edward Kmett's head.

Why not F# or OCaml?

I haven't used either F# or OCaml. However, here are my guesses:

  • At least some people are hell-bent on laziness. (I don't know whether it's a good or a bad thing.)
  • Many more people care about purity β€” F# is impure. I suspect that even if purity turned out to be a hindrance for "boring production", a lot of otherwise production-minded people either find that it matches their mindset, or just like it and don't want to give it up, etc.
  • Some people are probably driven away by .NET / Microsoft / managed runtime, regardless of how good F# is otherwise.
  • I have never used OCaml but it looks like it's simply bad on a bunch of metrics, including ecosystem poverty ("we had to build a Unicode string library ourselves", huh).
  • I think GHC's RTS is best-in-class? Not sure though.

What would be the exact differences between Haskell and Boring Haskell?

I don't know. This would very much depend on who actually kickstarts Boring Haskell.

Probably, we'll get a lot of stuff from Michael Snoyman's "Haskell: The Bad Parts" series: part 1, part 2, part 3.

A bunch of GHC warnings might become default and/or turn into errors.

I actually don't expect anything radical to happen at first; likely, the languages will start diverging with time as the compiler teams prioritize differently and/or different things will get funded. Growing apart organically is much easier than being bold and throwing features out immediately.

Why would anybody use Boring Haskell then if the languages would be very similar at first?

It's so, so, so nice to be using something that aligns with your goals. If Boring Haskell happened, I would probably wait a year (just to see whether it dies or not) and then start using it even if it only makes minimal changes.

Why not just avoid the features you don't want to use?

I think that when your community is significantly volunteer-driven, the abundance of features might actually hurt the ecosystem β€” and commercial development relies on the maturity of the ecosystem. That is, I suspect that a) a smaller community with more narrow goals will produce a better ecosystem, and b) limiting the ways in which things can get done will also result in a better ecosystem.

Example: Haskell has N different ways to write a type-safe SQL library (with generics, with type-level schema declarations, with GADTs, with Template Haskell, etc). Correspondingly, we have N half-baked SQL libraries instead of a few good ones. I suspect that this is partly because writing a new proof-of-concept library is more fun than contributing to an existing one.

And, in turn, having N libraries probably means that there are fewer tutorials covering each library. Which makes using them harder.

As long as this kind of fun will remain an option, it will keep distracting people. By somewhat dialing the fun down, we might be able to change the output of the (volunteer-driven) community.

(Example: I don't know the Rust ecosystem enough, but it looks to me that their situation with SQL libraries is much better β€” everybody just seems to use Diesel. While in the Haskell land we have Beam, Persistent+Esqueleto, Opaleye, Squeal, Selda, and no clear winner among those.)

(Update: I am told that Esqueleto significantly improved in v3.4, so perhaps we do have a good DB library in Haskell after all. I haven't checked it myself yet.)

I don't see how you can limit the features a community uses.

Counterexample: there is already a chunk of the Haskell community that tries to adhere to Haskell 98. Their share is probably decreasing, though.

If there was a community norm that "not using features beyond [latest standard] in production is a good and desirable thing", this would effectively limit the features. You might say "why don't we institute this norm" then, but I don't think you can institute such a norm in the existing community, not without bringing some kind of benefit to them β€” e.g. an alternative to GHC that is faster but supports fewer features.

This would also de-facto split the community, even if the compiler remains "Haskell".

How would it lead to better libraries though?

If there is a norm to use the [latest standard] and nothing beyond that, there could very well emerge a single library that all adherents of the [latest standard] are using.

And, even if it had no documentation at all, it would likely still have enough third-party tutorials to blow e.g. Beam documentation out of the water.

Unrelatedly: I don't see Snoyman preventing Dependent Haskell (or whatever other advanced features) from happening earlier.

I haven't mentioned Snoyman anywhere, have I.

This said: Snoyman himself doesn't prevent advanced features from happening, sure. Does the whole "boring production" chunk of the community prevent them from happening? This is more debatable.

  • Does SPJ have more research-heavy things to do than to organize Haskell Foundation, whose goals seem to lie squarely outside of research?
  • Is the adoption of Backpack, a somewhat research-y thing (though not in the types area), hindered because Stack does not support it?
  • Would we get dependent types faster if we cared less about compilation time? ("On the implementation side, work is coming along, but Simon and I have found that every step we take is more difficult than we expected. GHC is big! And it seems very hard to make changes without introducing performance regressions, which take a long time to debug." β€” @goldfirere on Reddit)
  • Would various Dependent Haskell related proposals be discussed and merged faster if fewer people in the community had a notion that "We don't yet have a spec for [Dependent Haskell], and thus making big changes in its name seems like putting the cart before the horse"? (β€” @isovector on GitHub)
    • It sure does seem easier to have more awareness of Dependent Haskell in the community if we optimize for the awareness of Dependent Haskell in the community rather than for "increasing adoption of Haskell in industry".
  • Would linear types get implemented β€” and consequently explored β€” faster if there were no qualms about them potentially creating confusion for people who aren't opting into -XLinearTypes?
    • Note that "Error messages must remain free of mention of linear types" and "Compile times for programs without -XLinearTypes must not unduly increase" and "There must be no degradation in runtime performance of GHC-compiled programs" were hard conditions put on the authors of the linear types proposal; so -XLinearTypes was merged into GHC 9.0 with major omissions, but at least error messages remained free of mention of linear types.
    • (Although I don't know how much it influenced things.)

"If instead of schisms and blessed-language-subsets, we as a community focus on the discussion of best practices, practical successes, and useful development patterns, we may attract new users and grow Haskell's use in industry, among hobbyists, or in research."

Thanks to u/nuptions for the formulation.

I think you have missed the point.

I am not interested in growing Haskell's use in industry, among hobbyists, or in research. As I have explained in part I, my interest is in researching how to marry advanced language features with production β€” this goal is not helped when a large chunk of the community doesn't care about achieving it.