The problems were all from Project Euler, so they were the sorts of things that tend to have deeply recursive solutions. So, in that department, F# was an advantage.
F# has some unpleasant quirks, though:
Monomorphism by default
We had this function:
let fibStep (a,b) = (b,a+b)By default, it only works on ints! It should be valid for any numeric type! It's just addition! But no, we had to label the parameters:
let fibStep (a : BigInt ,b : BigInt) = (b,a+b)Crippled type inference
Maybe I've been spoiled by Haskell, but I just assume that if I've got type inference, I've got Hindley–Milner over the entire program. In F#, types are only inferred within the boundaries of a single function. That means more type annotations.
Recursion requires annotation
And for some reason I don't understand, by default recursion is forbidden in a function, unless you define it with the "let rec" keyword. I have no idea why.
Find the missing library
Since F# is on the CLR, it inherits some VM design smells. Where's the Bigint type? Microsoft.FSharp.Math . You know, I would have expected the F# language to have implicit access to the FSharp namespaces. Nope.
Unusual punctuation
We knew about the confused usage of ;; for end of line and ; for comma, and , for a different kind of comma. But we kept having to look up operators (for method names we had autocomplete in the IDE! but dingbats were Google's territory.) I know we got confused on: cons (::), append (@), exponent (**), mod (%).
Cryptic error messages
And when you get it wrong, the interpreter is worthless. It had a tendency to entirely fail to parse our functions, and give us line/column numbers at the end of the code, rather than at the problem spot. I can't remember what the messages we were getting said, but it sure seemed like they just said "This is wrong"
Hard to google
Several times we tried googling some common function names like "head" or "tail" or "append" and found that mixed with the keyword "F#" you get nothing but music results. Way to go, marketing wizards.