My Thoughts on OCaml vs Haskell/Rust in 2023

Some compact feedback on osa1’s post:

  • I agree that having “something like typeclasses” in OCaml would be nice, and that this is one the main pain points with OCaml these days.

  • I wasn’t so impressed with the criticism of the standard library. Most languages get weird issues with their standard library over time (for example people frequently complain about Haskell’s head function being in the prelude and have arguably “fragmented the ecosystem” with many alternative prelude proposals), and having other libraries offer better designs or better feature coverage is fine with me. We get into composability trouble for problem domains that require a sort of central coordination, for example Lwt vs. Async vs. Eio, but mixing stdlib-using code with core/containers-using code has never been much of an issue in my experience.

  • I broadly agree with the criticism of OCaml’s syntax, which has various flaws. Most language have syntactic flaws. Indentation-sensitive language have much less lack-of-bracketing-related flaws of course, but this comes with its own cost. I think that occasionally complaining about the syntax is an acceptable trade-off of using OCaml. (In fact people tried hard to offer better syntaxes at the time of the Camlp4 revised syntax, and most people never bothered because the issues of the current syntax are not that bad in practice.) I do wish we had better syntax error messages, and there is slow-but-existing progress on that (lrgrep)

My thoughts on @sid’s post:

  • I think that comparing OCaml and Haskell is fine, but I think that people also have a point to compare to larger ecosystems with better tooling (in some respects), such as the JVM or the dotnet ecosystem.

  • I agree that OCaml is “practical” and I think that is one of its main strength among the nice functional programming langages out there, even including Rust. If you forget about the tooling for a minute and think just of the code, programming in OCaml is typically easier than programming in Haskell or Rust, with a lower learning curve.

  • Another aspect that was not emphasized in either posts is that OCaml is, in some respects, “small”. The stdlib is small, the runtime is small, the language implementation is less sophisticated than many out there (including GHC, the JVM, dotNet runtimes, Javascript engines…). OCaml as its core is a 80/20 language, getting 80% of the benefits at 20% of the complexity. Other programming language implementations have managed that, for example Chez Scheme is rather impressive in this respect. And OCaml is arguably losing some of this simplicity as time passes. But I think it still matters when thinking about the whole system: OCaml has less sophisticated optimizations than Haskell and a less advanced type system, it doesn’t benefit from the impressive JIT optimizations provided by production dotNET or JVM runtimes, its compiler backend is nowhere as featureful as LLVM as used by Rust, etc., but it still gets a large fraction of the value of these sophisticated systems with simpler approaches, which (1) contribute to an overall simpler ecosystem (which I think is a virtue, even if users may not care directly), and (2) has beneficial side-effects in terms of user experience, for example: fast enough compile times, or a bearable experience using system tools (gdb, perf, etc.) to study a running program. I think that some of the downsides of OCaml and its implementation can be assessed more positively with this systemic quality in mind – which is no excuse to provide a bad experience overall, of course! (@sid touches a bit of this in the TL;DR paragraph at the end.)

  • In some ways, the OCaml runtime has arguably become more advanced than the Golang runtime (and maybe the Haskell runtime).

    I don’t agree with this and I think that it is the one aspect of the post where our affective relation to programming languages are putting rosy glasses on our eyes. The Go and Haskell runtimes are really impressive pieces of engineering and I they have years of production experience for mode of usages that we are now just trying in the OCaml world. Both the OCaml 4 and OCaml 5 runtimes are fine pieces of software, but I don’t think one could objectively see them as “more advanced” than the Go or GHC runtimes. It’s great that we have some primitive support for effects, but Go has had flexible control primitives underlying goroutines for a while, and Haskell (besides an impressive and sophisticated concurrent runtime and IO system) has recently benefitted from lexi-lambda’s impressive delimited-control primops work that certainly opens the door for runtime-supported algebraic effects for Haskell.

14 Likes