1
Hi everyone 
Iāve been using Haskell in production for the previous 8 years. Iāve been quite active in the Haskell community, and some of you may remember my past contributions to the community and the ecosystem.
For the last 8 months, Iāve been using OCaml at Bloomberg, and my focus switched to a different language from the ML family.
I wrote a blog post comparing two languages from my POV:
I tried to provide a reasonable and balanced overview of these two languages, although my experience in both is significantly different. I hope this blog post can give a rough idea of both languages 
And who knows, maybe both OCaml and Haskell can improve and get better by inspiring each other 
Enjoy! And let me know any feedback you have!
hasufell 2
If I come to an existing Haskell project, the worst thing previous developers could do⦠Well, my previous 8 years of Haskell experience canāt prepare me for that
Thatās why I feel more productive in OCaml.
Interestingly, John Carmack said something similar in an interview (I think with Lex Friedmann), when describing why he prefers C over more powerful languages (amongst other reasons): small language surface, easy onboarding, less over-engineering.
I wonder if thatās why he lost interest in Haskell too.
I personally donāt have a lot of trouble staying away from the half baked language features (type families is half baked) in my own projects, but yes, you get exposed anyway.
atravers 3
I would have thought an incremental approach would be the best option here: surely it must be easier to see what feature or extension is required after putting together a small prototype, rather than trying to imagine whatās best to use before any code has been written.
Just use the basic features of the language to begin with for the prototype, adding more advanced ones only as needed (the developer equivalent of call-by-need :-) That way, if you find out later that some code has to be replaced, at least youāll be in a better situation than trying to envisage and do āeverything all at onceā only to find out that large parts of it was wasted effort.
P. S. I noticed in the comparison table an entry labelled Ergonomic mutability - in the interest of fairness, can an entry like Ergonomic laziness be added?
ChShersh 4
Same story here. I might avoid using them but I still spend that bit of mental effort when I first think about solving the problem. The knowledge cursed me.
And yes, I might avoid using those features, but thereās an entire community that uses those features in both OSS and industrial projects.
I once wasnāt able to finish a refactoring in a Haskell project at work because the project used a MultiParamTypeClass with 3 types, and I wasnāt able to figure out how to fix the GHC error message ![]()
ChShersh 5
Unfortunately, the cost of rewriting is often much higher than the cost of implementing for the first time ![]()
Also, time and money are limited. To understand the drawbacks of some features, you have to use them first. Thereās no other way. So those features are being used by various people in various projects (Iām guilty here as well). And now some other people have to maintain this legacy code.
This was enabled by the sole fact of having those features in the first place.
P. S. I noticed in the comparison table an entry labelled
Ergonomic mutability- in the interest of fairness, can an entry likeErgonomic lazinessbe added?
Thereās a point Laziness by default. I think itās the same as being ergonomic ![]()
I wonder if thatās why he lost interest in Haskell too.
I feel like there are so many issues with GHC (no way to restrict variable lifetimes; overreliance on GHC optimizations instead of a way to write low-level code directly), the ecosystem (datatype and C FFI libraries need to be written from scratch; everybody is afraid of laziness) and the functional approach as a whole (untrodden application design territory), that āhigh skill ceiling and features you donāt needā werenāt anywhere near the top of the complaint list.
I also feel like the community is in part to blame for the āIām more productive in other languagesā meme. Sure, the Simple Haskell pamphlet exists, but⦠itās a ākeep it simple, stupid, and donāt hurt yourselfā quotes page. Libraries donāt follow any of it, and in return noone expects simple extensible libraries. And at this point I donāt even think anyone cares.
atravers 7
Abso-howling-lutely! It would be nice to see an innovation in GHC that, for example, got rid of some great number of semi-related language extensions, make GHC run 80% faster, etc !
ā¦but as you also noted:
Since maintaining code also means rewriting it, there could be an opportunity to slowly (over time) refactor the problematic extensions out of existence (depending on how long youāll be around for in that project, of course). Then again, Iām no sociologist - I can envisage how I would react in a given situation much more easily than attempting to figure out what someone elseās reaction would be.
To me, bugs are bugs - if some language fad extension was a big enough failureā¦I would like to think that the organisation in charge of the codebase would consider that a bug, and be interested in a long-term plan for its removal (but also see note regarding sociology).
tdammers 8
Then again, restricting oneself to basic language features can also lead to code that is more complicated and harder to refactor or change.
atravers 9
Hence the emphasis on small prototypes - if you find a useful-enough language feature, thereās less code to rewrite.
I think you nailed it - ecosystem unstable enough to prevent relying upon large enough packages: even one dependency in a tree makes the entire build irreparably fail. Forcing the programmer to either rewrite majority of dependencies by herself from scratch (at cost absolutely prohibitive in real world), or freeze the entire toolchain for the lifetime of the product (again, completely impossible in the real world because of bugs and security fixes in both dependency packages and the toolchain itself).
Thereās less of it in Haskell now than a few years ago - but maybe enough to still keep it away from the industrial mainstream.
In my experience, C ecosystem doesnāt really have this problem: much fewer cases encountered, and fixes were trivial.
Thanks for this nice summary, and thanks for your eight years of contributions to Haskell. This part was my favourite:
Using Haskell tooling is like always being in the quantum superposition of āHow do you even use other PLs without such wholesome Haskell tools???ā and āHow Haskellers can live like that without these usability essentials???ā.
I find it hard to reconcile how excellent I believe our language is with the existence of so much flakiness and so many sharp edges in our ecosystem. The situation is improving though!
Regarding batteries included,
Iām a big proponent of the idea that a standard library should be batteries-included.
Iām sympathetic to the ābatteries includedā view of standard libraries, but it has its downsides too. For example, one reason that ByteString is not one of the batteries thatās included with base is because historically String was chosen to the battery fulfilling that role, and now itās very hard to displace.
Regarding error messages, I take your point that āthis is just one example (and most likely not the best one)ā so hereās an attempt at an example that is fairer, because it doesnāt involve typeclasses or overloading of operators and numeric literals (that OCaml doesnāt support anyway). OCamlās message is still better though.
ghci> True && [False, False, True]
<interactive>:1:9: error:
⢠Couldn't match expected type āBoolā with actual type ā[Bool]ā
⢠In the second argument of ā(&&)ā, namely ā[False, False, True]ā
In the expression: True && [False, False, True]
In an equation for āitā: it = True && [False, False, True]
hasufell 13
Iām not sure. I donāt see a general shift in perception. Some people here and there do the work. But that can easily regress once theyāre gone.
HF is somewhat frozen in the dilemma between building trust through support and diplomacy and actually executing their true goals. So I donāt see them taking over the work of maintaining a specific perception.
Most key projects are still incredibly isolated, some from their end-users, some from their contributors, some from each other.
Iām not sure. I donāt see a general shift in perception. Some people here and there do the work. But that can easily regress once theyāre gone.
I didnāt mention whoās doing the work or what happens when theyāre gone, I just mentioned the situation of flakiness and sharp edges is improving. Would you say that cabal and HLS are more flaky than, say, three years ago, less or the same?
ChShersh 15
Iām afraid after my honeymoon with Haskell was over, I became immune to having honeymoons with other languages because Haskell set a high threshold. I see trade-offs of different languages clearly and just follow my preference at my current time.
The ideal language for me doesnāt exist yet (because I havenāt written it yet) but thatās okay. As long as I can use any language I enjoy, Iām fine ![]()
ChShersh 17
Iām familiar with the downsides of this approach too ![]()
Still, trade-offs are everywhere, and in the end, I tend to follow my preference while being aware of all the pitfalls. I guess, I got bitten more by the lean standard libraries approach ![]()
Regarding error messages, I take your point that āthis is just one example (and most likely not the best one)ā so hereās an attempt at an example that is fairer, because it doesnāt involve typeclasses or overloading of operators and numeric literals (that OCaml doesnāt support anyway). OCamlās message is still better though.
True, Iām still a bit sour about this particularly confusing GHC behaviour ![]()
Actually, GHC error messages are even better now, as you get a stable unique error code which you can read more about online with examples and suggestions on how to fix them!
GHCi, version 9.8.1: https://www.haskell.org/ghc/ :? for help
ghci> True && [False, False, True]
<interactive>:1:9: error: [GHC-83865]
⢠Couldn't match expected type āBoolā with actual type ā[Bool]ā
⢠In the second argument of ā(&&)ā, namely ā[False, False, True]ā
In the expression: True && [False, False, True]
In an equation for āitā: it = True && [False, False, True]
hasufell 18
The ideal language for my would be a set of languages that are easily interoperable and where I can pick the complexity level I get exposed to based on the problem at hand.
C#, F# and F* somewhat go into that direction, but itās still a long way.
Haskell seems to go the āletās retrofit whatever we canā route. Iām not a fan of that approach.
yawaramin 19
Actually, in this case Haskellās message is still better than OCamlās:
# true && [false; false; true];;
Error: this variant expression is expected to have type bool
There is no constructor :: within type bool
We can thank OCamlās ātype-directed disambiguationā of constructors for this ambiguous error.
ocramz 20
In less nebulous terms? The first step to fixing problems is defining them clearly.
treblacy 21
But this is how the feature shoot-out trade-off table should really end:
| lang | research potential | stability (ā“ production use, comfort zone) |
|---|---|---|
| haskell | more | less |
| ocaml | less | more |
cobol (sorry couldnāt resist ) |
none | infinite |
Lately Iāve been working a lot with Standard ML (so basically OCamlā) and one thing I absolutely miss is generic deriving. For the codebase I need to define basically a map function for every datatype, but without typeclasses and generic deriving I have to write all of this error prone boilerplate myself.
Related to this is newtypes, I miss them a lot. IMO deriving (via)/newtypes is by far the best haskell feature
What I like in Ocaml is that letrec is explicit, so i can easily shadow variables so the earlier assignment is out of scope in the rest of the function.
)