Thanks for the detailed reply.
- The module system -- a very intuitive way to structure code
I see the module system used two ways in production - one is for trivial code-sharing, like to generate Map submodules. The other is for completely incomprehensible nonsense that makes it nearly impossible to find the actual definition of the thing you want. I find typeclasses easier and more ergonomic to use for both the trivial cases (like maps) and complex cases (like json codec generation, for which OCaml still uses the rough equivalent of the basically-deprecated Template Haskell).
- Poly variants
I agree, this is nice.
- Strictness -- predictable performance and easy debugging
I’ve always found this complaint overrated. Sure, it’s slightly annoying sometimes, but surely worth the language-wide discipline that comes with it.
- Allowing side effects
This substantially lowers the quality of production OCaml code compared to Haskell. Tons more spaghetti code, tons of global variables, etc etc.
Obviously purity is kind of a religious argument at this point, but in practice I have observed that it’s a liability.
- Private types -- better than newtypes imo since you can upcast to it's structural counterpart
I’ve never seen this in production. I had to look it up. Indeed, the first article is a blog post along the lines of “why is this useful”?
Haskell also supports casting newtypes via Coercible.
- Really good type inference -- you never have to write type signatures. Haskell and Purescript type inference is ok-ish and sometimes craps out, which is part of why type signatures for each function is recommended.
Haskell type declarations are usually only required with extensions. All OCaml style guides recommend writing type declarations in mli files anyway. The OCaml type system can occasionally infer things more easily because it’s so much weaker - cf the value restriction, no HKTs, etc.
- Stupidly fast compiler -- yes it matters, try contributing to the Idris codebase. It's like trying to contribute to the linux kernel, you'll wait 30+ minutes for it to compile.
Based on my coworkers who do performance optimization on OCaml code, it’s probably because the compiler isn’t optimizing much. But I don’t know much about that first hand. Also, have you tried GHCID or similar? Makes Haskell compilation very fast while developing.
- Very fast programs
Not an advantage over Haskell. They fare similarly in contrived competitions, and I have some suspicions that it’s easier to make Haskell code faster in practice. Some of the shit we do for speed in OCaml is very ugly. OCaml also suffers from very poor GC latencies compared to Haskell. I’ve seen multiple-minute(!) GC pauses in OCaml programs with a few dozen gigs of allocated memory. Never seen anything even close to that with Haskell.
- An actual package manager (stack uninstall?)
I guess I don’t appreciate the benefit of this over the stack model of tightly versioned automatic dependency resolution. Can you expand on some benefits?
- Modular implicits - a more sound ad hoc polymorphism system than typeclasses. Typeclasses can't handle simple things like if half of the Haskell ecosystem uses one Filterable typeclass and the other half uses a different Filterable.
That is by design and seems good to me. Why the hell would I want there to be two different Filterable typeclasses?
The ergonomics of MI remain to be seen but I suspect they will still be more annoying than compiler-resolved typeclasses.
- Algebraic effects - a strongly typed system for writing effects that will be part of multicore -- delimited continuations / conditions and restarts
This is basically vaporware at the moment. I agree it sounds nice, but I have no reason to believe we’ll see it in production in the next decade, and if we do it will probably look a lot more constrained than the idealized model people talk about.