Why is there a difference between type signatures of the same F # function in a module vs class?
Closely related to my question here , but actually a different question ...
Consider the following F #: -
type TestClass() =
let getValFromMap m k = Map.find k m
let mutable someMap : Map<string,int> = Map.empty
let getValFromMapPartial key = getValFromMap someMap key
let getValFromMapPartialAndTacit = getValFromMap someMap
module TestModule =
let getValFromMap m k = Map.find k m
let mutable someMap : Map<string,int> = Map.empty
let getValFromMapPartial key = getValFromMap someMap key
let getValFromMapPartialAndTacit = getValFromMap someMap
In class case and module case, getValFromMapPartial
both getValFromMapPartialAndTacit
behave differently and are compiled in IL differently. In both the class and module case, the former behaves like a true syntactic function, and the latter behaves like a lambda calculation function (I know this thanks to user Marc Sigrist).
In the modular case, the type signatures seem to be correct: -
getValFromMapPartial : key:string -> int
getValFromMapPartialAndTacit : (string -> int)
But in the case of class, the type signatures are identical: -
getValFromMapPartial : (string -> int)
getValFromMapPartialAndTacit : (string -> int)
Why is this so?
Since it getValFromMapPartial
acts like a true syntax function in both cases, why would it be typed like a lambda evaluation function in the class case?
source to share
I can only think of a few cases that you would ever need to worry about the difference between A -> B
and (A -> B)
(see the F # spec section on signature matching for relevant comments):
- If you want to implement a module signature, only a syntax function can implement something with a signature
A -> B
, whereas a syntax function or any other function value can implement a signature(A -> B)
. That is, the last signature is a superset of the first. - When you care about how your code appears in other .NET languages, signature functions are
A -> B
implemented as methods, and signature functions are(A -> B)
implemented as type valuesMicrosoft.FSharp.Core.FSharpFunc<A,B>
.
Otherwise, the difference doesn't matter. And in this case, as @ildjarn notes, the let-bound values ββin the type definition are private, so the above two considerations don't come into play for TestClass
, and it's just an implementation detail that has no implications.
source to share