为什么F#currying"变平"功能类型?

时间:2015-06-18 12:34:35

标签: f#

以下功能:

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的函数类型?

1 个答案:

答案 0 :(得分:7)

括号表示&#34; FsharpFunc&lt; _&gt;&#34;类型的值,而没有括号表示&#34;真CLR方法&#34;。在您的示例中,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);
    }
}

总而言之,我想要指出,这种区别在实践中并不重要,除非你练习一些非常黑暗的魔法,所以你不应该担心它。