What are my options?
- PureScript on web and Node.js
Can use NPM packages! Node.js as a run-time lacks features like shared memory across threads. PureScript is still too early IMO.
- Scala on JVM and web using Scala.js
Not a bad option, although the language is very complex. More towards the OOP end than the ML end in the spectrum of language design. JVM can be a good or a bad thing, depending on what you are doing.
- F# on .NET Core and web using Fable
Simple functional language with access to the .NET ecosystem. ASP.NET has great performance. Access to NPM packages on web. Lacks some advanced type-system features in Haskell, OCaml and Scala. However, the community has a pragmatic focus as a result.
- OCaml and ReasonML
ReasonML has limited backing from Facebook. OCaml has support from a few financial institutions (e.g. Jane Street) but it's not on the same level as what a big tech company could provide. Tiny (but high quality) community and ecosystem. OCaml has great single-threaded performance but mult-threading is not quite ready. Already small community split by compiler extensions and standard libraries.
- Haskell and GHCJS
Again, tiny community and ecosystem. Beautiful language, but lazy evaluation has bit me too many times. Steep learning curve since newcomers cannot fall-back to OOP and imperative code.
- Elm
Tiny ecosystem, tied to Node.js (see PureScript). Interop story with NPM modules is worse than PureScript.
For me, F# is the clear winner.
If you aren't particularly interested in functional programming - maybe you just use some delegates here and there - then C# is a fine choice. Otherwise, C# quickly becomes awkward compared to F#. Besides, C# to JS options are not as mature as Fable.