3

与我的问题密切相关,但实际上是一个不同的问题......

考虑以下 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

在类案例和模块案例中,getValFromMapPartial行为getValFromMapPartialAndTacit方式非常不同,并且编译为 IL 的方式也不同。在类和模块的情况下,前者表现得像一个真正的句法函数,而后者表现得像一个 lambda 计算函数(感谢用户 Marc Sigrist,我知道这一点)。

在模块情况下,类型签名似乎是正确的:-

getValFromMapPartial : key:string -> int
getValFromMapPartialAndTacit : (string -> int)

但是在的情况下,类型签名是相同的:-

getValFromMapPartial : (string -> int)
getValFromMapPartialAndTacit : (string -> int)

为什么会这样?

既然getValFromMapPartial在这两种情况下都充当真正的句法函数,为什么在类情况下它会被键入为 lambda 计算函数?

4

1 回答 1

5

我只能想到几次您需要担心A -> B和之间的区别(A -> B)(有关相关评论,请参阅 F# 规范的签名一致性部分):

  • 当你想实现一个模块签名时,只有一个语法函数可以作为带有签名的东西的实现A -> B,而一个语法函数或任何其他函数值都可以实现签名(A -> B)。也就是说,后者的签名是前者的超集。
  • 当您关心您的代码在其他 .NET 语言中的显示方式时,带有签名的函数A -> B被实现为方法,而带有签名的函数(A -> B)被实现为 type 的值Microsoft.FSharp.Core.FSharpFunc<A,B>

否则,差异并不重要。在这种情况下,正如@ildjarn 所指出的,类型定义中的 let-bound 值是私有的,因此上述两个考虑因素不会发挥作用TestClass,它只是一个没有影响的实现细节。

于 2014-11-20T20:51:16.620 回答