以下功能:
let twoInputs x y =
let sum = x + y
let product a = sum * a
product
有类型:
val twoInputs : x:int -> y:int -> (int -> int)
这完全合理,我明白为什么会来。但为什么这个功能:
let oneInput = twoInputs 1
的类型为val oneInput : (int -> int -> int)
?
不应该是int -> (int -> int)
吗?
此外,我认为上述功能应符合Associative property,因此int -> int -> (int -> int)
和int -> int -> int -> int
之间应该没有区别。如果是这样,为什么不将后者指定为twoInputs
的函数类型?
答案 0 :(得分:7)
括号表示" FsharpFunc< _>"类型的值,而没有括号表示"真CLR方法"。在您的示例中,twoInput
被编译为真正的CLR方法,但返回类型FSharpFunc<_>
的值,因此返回其类型。但是您的oneInput
被编译为类型为FSharpFunc<_>
的类字段,因此也是其类型。
你甚至可以实现相同的效果(即将真正的方法转化为价值),即使没有干扰,也很简单:
> let twoInputs x y =
> let sum = x + y
> let product a = sum * a
> product
> let twoInputsAgain = twoInputs
val twoInputs : x:int -> y:int -> (int -> int)
val twoInputsAgain : (int -> int -> int -> int)
这是因为CLR不支持&#34;分配方法&#34;的概念,所以F#必须通过将twoInputsAgain
声明为FSharpFunc<_>
类型的字段来编译它然后为其分配一个继承自FSharpFunc<_>
的类的实例,并在twoInputs
d时调用Invoke
。
如果你将它反编译为C#(我使用ILSpy),你就会看到:
static $Program()
{
$Program.twoInputsAgain@11 = new Program.twoInputsAgain@11();
}
internal class twoInputsAgain@11 : OptimizedClosures.FSharpFunc<int, int, FSharpFunc<int, int>>
{
public override FSharpFunc<int, int> Invoke(int x, int y)
{
return Program.twoInputs(x, y);
}
}
总而言之,我想要指出,这种区别在实践中并不重要,除非你练习一些非常黑暗的魔法,所以你不应该担心它。