currying和部分应用有什么区别?

坚强是说给别人听的谎言 提交于 2020-02-27 05:46:48

我经常在互联网上看到各种各样的抱怨,其他人的currying例子并不是currying,但实际上只是部分应用。

我没有找到关于部分应用是什么的合理解释,或者它与currying有何不同。 似乎存在普遍的混淆,在某些地方将等效的例子描述为currying,在其他地方描述为部分应用。

有人可以向我提供这两个术语的定义,以及它们如何区别的细节吗?


#1楼

注意:这是从F#Basics中获取的,这是.NET开发人员进入函数式编程的优秀介绍性文章。

Currying意味着将具有许多参数的函数分解为一系列函数,每个函数都接受一个参数并最终产生与原始函数相同的结果。 对于功能编程新手来说,Currying可能是最具挑战性的话题,特别是因为它经常与部分应用混淆。 您可以在此示例中看到两者都在工作:

let multiply xy = x * y let double = multiply 2 let ten = double 5

您应该立即看到与大多数命令式语言不同的行为。 第二个语句通过将一个参数传递给一个带两个的函数来创建一个名为double的新函数。 结果是一个函数,它接受一个int参数并产生相同的输出,就好像你已经调用了multiply,x等于2,y等于那个参数。 在行为方面,它与此代码相同:

let double2 z = multiply 2 z

通常,人们错误地认为乘法是形成双重的。 但这只是有点真实。 乘法函数是curry,但是在定义时会发生这种情况,因为默认情况下F#中的函数是curry。 当创建双重函数时,更准确地说,部分应用了乘法函数。

乘法函数实际上是一系列两个函数。 第一个函数接受一个int参数并返回另一个函数,有效地将x绑定到特定值。 此函数还接受一个int参数,您可以将其视为绑定到y的值。 在调用第二个函数之后,x和y都被绑定,因此结果是x和y的乘积,如double体中所定义。

要创建double,将计算乘法函数链中的第一个函数以部分应用乘法。 结果函数的名称为double。 当计算double时,它使用其参数以及部分应用的值来创建结果。


#2楼

我在另一个主题https://stackoverflow.com/a/12846865/1685865中回答了这个问题。 简而言之,部分函数应用程序是关于修复给定多变量函数的一些参数以产生具有较少参数的另一个函数,而Currying是关于将N个参数的函数转换为返回一元函数的一元函数... [示例在这篇文章的末尾显示了Currying。]

Currying主要是理论上的兴趣:人们可以仅使用一元函数来表达计算(即每个函数都是一元的)。 在实践中和作为副产品,如果语言具有curried功能,它是一种可以使许多有用(但不是全部)部分功能应用程序变得微不足道的技术。 同样,它不是实现部分应用程序的唯一方法。 因此,您可能会遇到以其他方式完成部分应用程序的情况,但人们将其误认为是Currying。

(Currying的例子)

在实践中,人们不会只写

lambda x: lambda y: lambda z: x + y + z

或等效的JavaScript

function (x) { return function (y){ return function (z){ return x + y + z }}}

代替

lambda x, y, z: x + y + z

为了Currying。


#3楼

对我来说,部分应用程序必须创建一个新函数,其中使用的参数完全集成到结果函数中。

大多数函数式语言通过返回闭包来实现currying:在部分应用时不要在lambda下求值。 因此,对于有趣的部分应用,我们需要在currying和部分应用之间做出区别,并将部分应用视为curda和lambda下的评估。


#4楼

通过以下JavaScript示例可以最好地说明curry和部分应用程序之间的区别:

function f(x, y, z) {
    return x + y + z;
}

var partial = f.bind(null, 1);

6 === partial(2, 3);

部分应用导致更小的功能; 在上面的例子中, f的arity为3,而partial只有2的arity。更重要的是,部分应用的函数会在调用时立即返回结果 ,而不是currying链中的另一个函数。 因此,如果你看到像partial(2)(3)这样的东西,它实际上不是部分应用。

进一步阅读:


#5楼

有趣的问题。 经过一番搜索后, “部分功能应用程序没有进行调整”给出了我发现的最佳解释。 我不能说实际差异对我来说特别明显,但后来我不是FP专家......

另一个有用的页面(我承认我尚未完全阅读)是“使用Java闭包进行Currying和部分应用程序”

看起来这看起来像是一对广泛混淆的术语,请注意。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!