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?

+3


source to share


1 answer


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 values Microsoft.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.

+5


source







All Articles