I employ some strategies when I work with OCaml to avoid some of these pain points: I avoid libraries with poor documentation, funky types, and preprocessors that don't throw proper error messages. So I skip ocamllex, Menhir and Reasonml because I've found like OP that the DX is too poor..
But otherwise I don't particularly agree with OPs pain points. I personally find OCaml's syntax to be great. Very easy to write and read once you're used to it. And I previously thought that it's very important to annotate all types, as it would help with my thinking, but these days I find I'm more productive when I write out the code without types, maybe add a type here and there. I only annotate if OCaml's deduced type is too complex or generic.
Maybe it’ll grow on me as I get used to it :) but e.g. I was really confused about a nonsense error in a match statement until I realized that it was because of a nested match statement.
If you don’t use ocamllex/Menhir, what do you use for parsing & compiling?
> I was really confused about a nonsense error in a match statement until I realized that it was because of a nested match statement.
This kind of confusion instantly goes away when you use auto-formatting with ocamlformat, which is the recommended formatting tool for the OCaml platform. It would line up your match cases in such a way that you would be able to almost immediately tell that the compiler is interpreting the dangling cases as part of the inner match.
If so, that would be unfortunate... because the whole raison d'etre of ReasonML is DX! Specifically, to provide a more familiar syntax for programmers coming from the curly-brace world.
But otherwise I don't particularly agree with OPs pain points. I personally find OCaml's syntax to be great. Very easy to write and read once you're used to it. And I previously thought that it's very important to annotate all types, as it would help with my thinking, but these days I find I'm more productive when I write out the code without types, maybe add a type here and there. I only annotate if OCaml's deduced type is too complex or generic.