EDIT: I wouldn't choose TypeScript either for this type of use case, but not for the reasons they state, that's my point
EDIT: I wouldn't choose TypeScript either for this type of use case, but not for the reasons they state, that's my point
Ocaml has a top in class typesystem, a "faster than Go" compiler and (in 2025) good tooling. It allows you to say fuck it and write a while loop if you need to. Hell you can even do OOP. Also it has an incredible module system and full type inference. It also has an effect system, and good concurrency features (ocaml 5).
I cant say many other languages that has all the same features.
And OCaml excels at solving that sort of problem. OCaml and Erlang are the only two languages that I'm aware of that have a really clean way of doing this, in most other languages there is always some kind of kludge or hack to make it work and at best you're going to do something probabilistic: it seems to work, even under load, so it probably is good now. Until six weeks later on an idle Tuesday the system deadlocks and you have no idea how it happened.
Haskell has a steeper learning curve IMHO: monads are pervasive and are hard to understand, laziness isn't a common programming pattern and it adds complexity. I find type classes confusing as well, it's not always clear where things are defined.
I like that OCaml is close to the hardware, there are no complex abstractions. The module system makes it easy to program in the large (I love mli). If you avoid the more advanced features, it's a super simple language.
[0] I think most people just end up post-rationalizing whatever choice they have already invested in, I know I do :) With that in mind, maybe I as a mainly-Haskell dev should instead list some things I miss from OCaml: faster compile times, non-recursive `let` by default, polymorphic variants, labeled arguments
Ocaml is more practical, and less punishing (you can do IO without monads), but the most important diffrence is performance. Haskell is VERY hard to make predictable because its lazy. Ocaml is strict so general system performance is much easier to predict.
But they are sibling languages in my book, while i still prefer ocaml over haskell.
A big part of interacting with APIs (which I imagine Stategraph does) is just dealing with records, and working with records in Haskell is really annoying unless you bring in lenses which bring a lot of complexity.
TypeScript has soundness issues that OCaml does not have
• Strongly-typed data structures catch field errors at compile time
TypeScript does have this, although the guarantees are in practice weaker since libraries may have incorrect type definitions
• Type-safe SQL queries prevent schema drift before deployment
There are TypeScript libraries that offer this, so fair point!
• Immutability by default eliminates race conditions
TypeScript is not immutable by default
• PPX generates correct JSON serialization automatically
TypeScript does not have an equivalent to PPX infrastructure AFAIK. If there is, it's definitely not as widely used within the ecosystem compared to PPX for OCaml.
Edit: Downvoters care to respond?
This blog post shows the elements of OCaml that motivate us to use it. Is it complete? No. Maybe it should be more explicit that we like using OCaml, and these technical aspects aren't unique but certainly benefits we see.
OCaml as the discussion subject on this thread, allows for mutable data structures, and I am old enough to have been taught Lisp as one possible avenue for FP.
Even Haskell is not functional in the strictest sense. It has unsafe IO. It can throw exceptions. Functions may not halt.
My point was that without any escape hatches or magic you can code a segfault starting in ocaml5. That may be true of haskell? It is true of rust too, though the only known way to do it isn't something that is likely to happen by accident and is tracked as a bug. In ocaml5 if you use domain, it is down to experience skill, and some luck to be sure you used atomic when necessary. I'm a bad programmer despite going on four decades of experience. I'm not even remotely methodical. If I adopt ocaml for a project I'm using 4 or adding something that fails the pipeline if it finds domain anywhere.
It shouldn't, the OCaml 5 memory model bounds the reach of data races in both space and time. [1] Thread-unsafe code won't be correct when misused, but it will stay memory safe unless you reach for an additional escape hatch (or you find an implementation bug of course).
[1]: https://ocaml.org/manual/5.4/memorymodel.html
I'm much more concerned about the amount of poorly vetted escape hatches in wide use in OCaml, mainly for bindings.
Edit: i was wrong! Since at least 5.1 it catches the cross domain access and errors gracefully.
A loop by itself is not non-fp, as i can do the exact same thing via recursion. Its just syntax.
Hell, i can write a never halting program in lambda calculus with a fixed point combinator causing "undefined behaviour".
The real question is "why not Rust?". I've used both a fair bit and OCaml's only major advantage IMO is compile time. That doesn't seem compelling enough to put up with the downsides to me.
I know that isn't everyone's view, but I do hope posts like this, even if not technicaly deep, at least let people know that there are lots of options out there.
Occasionally I do still fight it, e.g. if you want a self-borrowing structure there still isn't a great solution (I think Rust should support position independent borrows) but overall it's fine.