Why the difference between type signatures of the same F# function in module vs class?

f#, partial-application, pointfree, tacit-programming

Solution

I can only think of a few times you'd ever need to worry about the distinction between `A -> B` and `(A -> B)` (see the F# spec's section on signature conformance for related commentary):

- When you want to implement a module signature, only a syntactic function can serve as the implementation of something with the signature `A -> B`, while either a syntactic function or any other function value could implement the signature `(A -> B)`. That is, the latter signature is a superset of the former.

- When you care about the way your code appears to other .NET languages, functions with signature `A -> B` are implemented as methods, while functions with signature `(A -> B)` are implemented as values of type `Microsoft.FSharp.Core.FSharpFunc<A,B>`.

Otherwise, the difference doesn't matter. And in this case, as @ildjarn notes, let-bound values in a type definition are private, so the above two considerations don't come into play for `TestClass` and it's just an implementation detail of no consequence.

Problem

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 both the class case and the module case, `getValFromMapPartial` and `getValFromMapPartialAndTacit` behave in very different ways, and are compiled to IL differently. In both the class and module case, the former behaves like a true syntactic function, and the latter behaves like a lambda-computing function (I know this thanks to user Marc Sigrist). In the module case, the type signatures seem to be correct:- ``` getValFromMapPartial : key:string -> int getValFromMapPartialAndTacit : (string -> int) ``` But in the class case, the type signatures are identical:- ``` getValFromMapPartial : (string -> int) getValFromMapPartialAndTacit : (string -> int) ``` Why would this be so? Since `getValFromMapPartial` acts as a true syntactic function in both cases, why would it be typed as a lambda-computing function in the class case?

Original source