什么是“可折叠”功能的正式术语?

时间:2011-11-11 18:50:11

标签: linq function math language-agnostic functional-programming

我经常使用LINQ Aggregate运算符。从本质上讲,它允许您通过在函数的最后一个计算值和序列的下一个元素上重复应用函数,在序列上“累积”一个函数。

例如:

int[] numbers = ...
int result = numbers.Aggregate(0, (result, next) => result + next * next);

将计算数组元素的平方和。

经过一些谷歌搜索后,我发现函数式编程中的一般术语是"fold"

现在我认为可以使用此运算符计算的函数只需要满足(如果我错了,请纠正我):

f(x1, x2, ..., xn) = f(f(x1, x2, ..., xn-1), xn)

这个属性似乎很常见,值得一个特殊的名字。有吗?

3 个答案:

答案 0 :(得分:3)

您可能正在寻找Iterated binary operation

您还需要添加一些停止条件,例如

f(x) = something
f(x1,x2) = something2

他们在我提供的链接中定义了二进制操作f和另一个函数F,以处理当你到达f(x1,x2)时会发生什么。

答案 1 :(得分:3)

在函数式编程中,fold用于聚合列表,数组,序列等集合的结果...... fold的表达式不正确,导致混淆。一个正确的表述可能是:

fold f e [x1, x2, x3,..., xn] = f((...f(f(f(e, x1),x2),x3)...), xn)

f的要求实际上非常宽松。可以说元素的类型是T,e的类型是U。所以函数f确实需要两个参数,第一个是类型U,第二个是类型T,并返回类型U的值(因为这个值会作为函数f的第一个参数再次提供)。简而言之,我们有一个带有签名f: U * T -> U的“累积”功能。 由于这个原因,我认为这些功能没有正式用语。

在您的示例中,e = 0T = intU = int和您的lambda函数(result, next) => result + next * next都有一个签名f: int * int -> int,符合“可折叠”的条件功能

如果你想知道,fold的另一个变种是foldBack,它会以xnx1的相反顺序累积结果:

   foldBack f [x1, x2,..., xn] e = f(x1,f(x2,...,f(n,e)...))

foldfoldBack返回相同的结果时,存在具有交换函数的有趣情况,其满足f(x,y)= f(x,y)。关于fold本身,它是类别理论中的一个特定的变形现象。您可以阅读有关catamorphism here的更多信息。

答案 2 :(得分:2)

澄清问题:'平方和'是一个特殊函数,因为它具有可以用折叠函数加上lambda表示的属性,即

sumSq = fold ((result, next) => result + next * next) 0

哪些功能f具有此属性,其中dom f = { A tuples }ran f :: B

显然,由于折叠的机制,f是可折叠的陈述是断言存在h :: A * B -> B,使得对于任何n> A,f ((x1,...xn)) = h (xn, f ((x1,...,xn-1)))中的0,x1,...,xn。

h存在的断言与您的条件几乎相同

f((x1, x2, ..., xn)) = f((f((x1, x2, ..., xn-1)), xn))     (*)

所以你几乎是正确的;区别在于您需要A=B,这比一般折叠可表达的功能更具限制性。但问题更多,折叠通常也会采用起始值a,设置为a = f nil。你的公式(*)错误的主要原因是它假设h是对列表中的f所做的,但只有在h(x, a) = a时才是这样。也就是说,在你的平方和的例子中,你给Accumulate的起始值是0,当你添加它时它没有任何作用,但是有折叠可表达的函数,其中起始值有效,在这种情况下我们具有折叠可表达的功能,不满足(*)。

例如,采用这种可折叠表达的函数lengthPlusOne

lengthPlusOne = fold  ((result, next) => result + 1) 1

f (1) = 2,但f(f(), 1) = f(1, 1) = 3

最后,让我们举一个关于折叠方面不能表达的列表上的函数的例子。假设我们有一个黑盒功能并在这些输入上测试它:

f (1) = 1
f (1, 1) = 1    (1)
f (2, 1) = 1
f (1, 2, 1) = 2 (2)

元组(=有限列表)上的这样一个函数显然存在(我们可以将它定义为具有上述输出并且在任何其他列表上为零)。然而,它不可折叠,因为(1)暗示h(1,1)=1,而(2)暗示h(1,1)=2

我不知道是否还有其他术语,而不仅仅是说“一种可以表达为折叠的功能”。也许(左/右)无上下文列表函数可能是描述它的好方法吗?