以下功能:
let twoInputs x y =
let sum = x + y
let product a = sum * a
product
Run Code Online (Sandbox Code Playgroud)
有类型:
val twoInputs : x:int -> y:int -> (int -> int)
Run Code Online (Sandbox Code Playgroud)
这是完全合理的,我明白为什么会到来.但为什么这个功能:
let oneInput = twoInputs 1
Run Code Online (Sandbox Code Playgroud)
是类型val oneInput : (int -> int -> int)?
不应该int -> (int -> int)吗?
另外,我认为上面的函数应该符合关联属性,所以int -> int -> (int -> int)和之间应该没有区别int -> int -> int -> int.如果是这样,为什么不将后者指定为函数类型twoInputs?
括号表示"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)
Run Code Online (Sandbox Code Playgroud)
发生这种情况是因为CLR不支持"分配方法"的概念,因此F#必须通过声明twoInputsAgain为类型字段来编译它FSharpFunc<_>,然后为其分配一个继承的类的实例,FSharpFunc<_>并twoInputs在Invoked 时调用.
如果您将其反编译为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);
}
}
Run Code Online (Sandbox Code Playgroud)
总而言之,我想要指出的是,这种区分在实践中并不重要,除非你练习一些非常黑暗的魔法,所以你不应该担心它.