So this is a classic value restriction problem. It is more apparent if you just do this block of code:
let foo (a: String)(b: 'm) =
printfn "%A - %A" a b
let fooWithA= foo "hello"
This will give the following error:
error FS0030: Value restriction. The value 'fooWithA' has been inferred to have generic type val fooWithA : ('_a -> unit)
Either make the arguments to 'fooWithA' explicit or, if you do not intend for it to be generic, add a type annotation.
The problem is that fooWithA
is not a proper function and as a result, it is not allowed to have a generic type.
So in the first example, the compiler sees that you are first calling it with a string, so it makes that specialization, which then fails for the integer and boolean cases.
In the second example you have implicitly created a function which can be made generic so all is good.
In the third example, you have the same problem as the first, you are binding the function to a value so it can't be generic.
The simplest solution to all this is to always use a function like so
let fooWithA a = foo "hello" a