为什么ML系列语言中的自动currying

时间:2017-07-08 05:06:10

标签: language-design currying ml

ML系列语言具有自动调整功能 - 其中带有两个参数的函数调用被认为是一次应用一个f x y = (f x) y - 而其他语言系列则不会。< / p>

这只是一次历史性事故,还是有技术原因?

请注意,我询问自动调整是好还是坏(这是一种主观判断)。我问它是否与ML系列语言的其他功能协同作用,以便更自然地包含在这些语言中,如果是这样,那些功能是什么以及协同作用的本质是什么?或者相反,是否有其他语言家族的功能会与任何提供自动currying的尝试发生冲突?

编辑:除了给定的答案之外,我发现可能还有另一个因素:如果您正在使用模式匹配的语言编写 编译器,那么它可以用于AST更加复杂,这意味着对于传统的用元组调用来说它是可以接受的。构造成复合词。因此,鉴于编译器通常使用自己的语言编写,自动currying和模式匹配可以很好地结合在一起。

2 个答案:

答案 0 :(得分:3)

由于标准ML支持元组(和其他记录)和模式匹配,因此它还支持 -currying模型:

fun add (x, y) = x + y

所以curried函数只是一个选项,对它们的特殊支持只是语法糖(虽然写作惯用的ML代码非常重要的语法糖)。 JavaScript 之类的语言没有理由提供相同的语法糖:

// Analogous to fun (f o g) x = f (g x) -- not actually valid JS:
function compose(f)(g)(arg) {
    return f(g(arg));
}

但由于JavaScript函数立即返回一个函数并不常见,因此这种语法糖在那里不会那么有用。 (当然,这有点循环:语言中常见的东西是由语言变得容易形成的,而语言使事情变得容易,因为它们在该语言中很常见。但是所有语言特征都是如此,而不是特定于这个。)

有趣的是,即使在标准ML中,特殊的curried-function语法仅适用于函数声明fun ...),而不适用于函数表达式({{ 1}}。所以我可以写

fn ...)

但不是

val op o = fn f => fn g => fn x => f (g x)
相反,在Haskell中,偶数函数表达式支持自动currying;例如,val op o = fn f g x => f (g x) (* illegal *) 评估为(\ x y z -> x + y + z) 3 4 5。 (Haskell还将currying视为另一方面的核心,即中缀运算符是curried函数,与标准ML不同,其中中缀运算符是一对函数。)

答案 1 :(得分:3)

这当然不是偶然的。

首先,它简化了语言:不需要将具有多个参数的函数作为单独的概念引入;每个函数都只有一个参数。多个参数可以通过元组或curry来表示。

其次,在实践中非常方便,因为依赖于部分应用的各种模式(例如,高阶函数,组合库等)证明了......