F# is a mashup of OCaml and the CLR. It's very productive and a lot of fun, but also a complete mess. It is too young to be this messy.
What's wrong with F#
- F# is very awkward as an imperative language, and a lot of the more imperative .net APIs end up feeling very clumsy.
- F# is somewhat compatible with a vaguely-defined subset of ocaml. This leads to cruft, lots of deprecated syntax and weirdness. This seems to have no tangible benefit--it's not like F# programmers are reusing ocaml libraries.
- OCaml's module system was summarily removed and nothing was made available to replace it. As a result, the language is completely unsuitable for large-scale or component-based programming.
- The anonymous function syntax is too verbose. It's downright depressing that C#'s lambda expression is cleaner.
- Calling into the .net api feels a little bit like doing interop--it's awkward to invoke methods with tuple'd arguments and you many explicit type conversions are needed.
- F#'s type inference is not powerful enough to cope with the CLR style method overloading. As a result, many more type annotations are required than would be in a similar OCaml program.
- The compiler is unacceptably slow. 10+ seconds to compile the <1000 lines of code that drive this wiki on mono/linux.
- There is tons of junk in the language that was clearly placed there to make it a good CLR language. Stuff like only supporting named/optional arguments for methods, but not for let-bindings.
F# has a business problem
F# will never be a great language because it lives in a business environment where it is marginal.
F# is subservient to C#. If C# supports a feature, it will make its way into the BCL, and then F# will be forced to consume it as-is. F#'s clumsy extensions for P/Invoke, the
mutable keyword, and the method-only support for named parameters are all instances of this problem.
WinRT, if it wasn't such a piece of shit, might possibly bring some hope. Unfortunately, it's just an improved iteration of COM IDL stuff, and not a real step in the direction of supporting abstract API that feels native across a wide variety of languages.
F# has a legacy problem
OCaml is an old language with old limitations. F# inherited many of these.
For example, in C# the assembly is a compilation unit, and mutually recursive types can be defined freely throughout the source files of the assembly.
In OCaml, this isn't allowed. Types must be declared in order. OCaml inherited this from SML, which, AFAIK, is this way because it makes proofs simpler. F# inherited this from OCaml, and as a result it is completely useless for object oriented programming.
The only reason OCaml isn't (according to some people) is the combination of the module system, the structural typing in OCaml's object system, and OCaml's type inference, which, somehow, together, ameliorate this problem.
FWIW, Haskell has much of the same stupidity because mutually recursive modules are a barely-supported GHC-only feature. It's unclear what saves them. Maybe it's because no-one builds large-scale software in Haskell. Maybe it's typeclasses. I don't know.