Part of the problem with adopting an ML is that it feels like a huge departure from mainstream software development. From the syntax, to the build tools, to the concepts one uses on a day-to-day basis, it can be hard to slog through to get to the point of feeling productive.
ReasonML is focusing on four things to help alleviate this friction from adoption:
1. Providing a more familiar syntax
2. Providing simple, high quality tooling built on top of a familiar ecosystem
3. Providing high quality documentation that focuses on onboarding developers who are coming from these other ecosystems
4. Providing a "killer-app" that can show the power of the language and draw peoples interest - in this case, Reason's integration with React through it's ReasonReact library and support for JSX.
I think that these 4 things really make a difference when getting "people onboard with an ML," which is why the ReasonML community is something that I'm betting on for the mid- to long-term future.
Just a few weeks ago I got an F# project with TensorFlowSharp up and running on OSX in VSCode with the ionide extension. It JustWorked™.
In any case, I'd suggest you give it a crack again if you are interested. The experience has improved greatly and the tooling seems pretty great now on Linux/OSX. I've been following it for 3-4 years though, so I certainly understand how it would seem like a non-starter in the recent past.
1. Record types are very inflexible. It is, for example, not trivial to do things like get a new record type by adding a few fields to an existing record types.
2. F# supports only explicit interfaces. Making records implement interfaces requires defining getters and setters for every property. And requires explicit casting when you are sending a record to a function that uses an interface.
When you don't control the types (as is often when working with third party libraries) this becomes a major annoyance especially when you are habituated to typescript's structural typing.
While I would like to see opaque types in typescript for some use cases, I really think having structural types, implicit interfaces and erased unions by default makes life a lot easier, especially when it comes to interop with wider js ecosystem.
At the end of the day it quickly becomes very obvious that where as typescript was built from ground up to embrace javascript ecosystem, F# was not. As a result, when targeting javascript, a lot of design decisions which were based on limitations of CLR being a C# focused object oriented platform come across as bizarre and jarring. For instance why do we need both modules and namespaces ? Why are statically resolved type parameters only supported in inline functions ?
I will admit that this can be very much a case of me being more familiar with typescript and not so much with F#.
I do have a deep appreciation for both F# and Fable teams who have been incredibly helpful in stackoverflow and gitter. I strongly prefer F#'s syntax despite being a full time JS/TS developer and F#'s type inference is far better than what typescript offers today and at times it feels almost magical.
I also think that Fable's approach for generating babel compliant AST and taking advantage of babel ecosystem is brilliant and something I'd like to see in more languages targeting javascript.
Nevertheless, the learning is curve with the latter has been significantly steeper and at places the error messages are bizarrely confusing. Thus, I am not yet fully convinced that for a bulk of frontend applications (I mostly work on enterprise applications for data analysis and visualization) the benefits of that learning curve are substantially justified especially if you don't have any existing investment on the .Net side.
Also, as I'm no longer a Windows developer, I have to say that .NET Core + F# + Mac is still not a great environment.
OCaml has functors, GADTs, better object system, nowadays it has an incredible developement pace and a huge amount of native libraries.