3 回答
TA贡献1827条经验 获得超8个赞
Currying将n个参数的单个函数转换为n个函数,每个函数都有一个参数。鉴于以下功能:
function f(x,y,z) { z(x(y));}
咖喱变成:
function f(x) { lambda(y) { lambda(z) { z(x(y)); } } }
为了获得f(x,y,z)的完整应用,您需要这样做:
f(x)(y)(z);
许多函数式语言都可以让你写f x y z。如果你只调用f x y或f(x)(y)那么你得到一个部分应用的函数 - 返回值是一个闭包,lambda(z){z(x(y))}传入x和y的值f(x,y)。
使用部分应用程序的一种方法是将函数定义为广义函数的部分应用程序,如fold:
function fold(combineFunction, accumulator, list) {/* ... */}
function sum = curry(fold)(lambda(accum,e){e+accum}))(0);
function length = curry(fold)(lambda(accum,_){1+accum})(empty-list);
function reverse = curry(fold)(lambda(accum,e){concat(e,accum)})(empty-list);
/* ... */
@list = [1, 2, 3, 4]
sum(list) //returns 10
@f = fold(lambda(accum,e){e+accum}) //f = lambda(accumulator,list) {/*...*/}
f(0,list) //returns 10
@g = f(0) //same as sum
g(list) //returns 10
TA贡献1898条经验 获得超8个赞
了解它们之间差异的最简单方法是考虑一个真实的例子。假设我们有一个函数Add
,它将2个数字作为输入并返回一个数字作为输出,例如Add(7, 5)
返回12
。在这种情况下:
使用
Add
值部分应用函数7
将为我们提供一个新函数作为输出。该函数本身需要1个数字作为输入并输出一个数字。因此:Partial(Add, 7); // returns a function f2 as output // f2 takes 1 number as input and returns a number as output
所以我们可以这样做:
f2 = Partial(Add, 7);f2(5); // returns 12; // f2(7)(5) is just a syntactic shortcut
哗众取宠的功能
Add
会给我们一个新的功能输出。该功能本身需要1号作为输入,并输出又另一个新的功能。然后第三个函数将1个数作为输入并返回一个数作为输出。因此:Curry(Add); // returns a function f2 as output // f2 takes 1 number as input and returns a function f3 as output // i.e. f2(number) = f3 // f3 takes 1 number as input and returns a number as output // i.e. f3(number) = number
所以我们可以这样做:
f2 = Curry(Add);f3 = f2(7);f3(5); // returns 12
换句话说,“currying”和“partial application”是两个完全不同的功能。Currying只需1个输入,而部分应用需要2个(或更多)输入。
即使它们都返回一个函数作为输出,返回的函数也是完全不同的形式,如上所示。
TA贡献1827条经验 获得超4个赞
注意:这是从F#Basics中获取的,这是.NET开发人员进入函数式编程的优秀介绍性文章。
Currying意味着将具有许多参数的函数分解为一系列函数,每个函数都接受一个参数并最终产生与原始函数相同的结果。对于功能编程新手来说,Currying可能是最具挑战性的话题,特别是因为它经常与部分应用混淆。您可以在此示例中看到两者都在工作:
let multiply x y = x * y let double = multiply 2let 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时,它使用其参数以及部分应用的值来创建结果。
添加回答
举报