2017-02-28 54 views
5

在一个在线课程中指出foldLeftfoldRight对于关联和交换的运营商是等效的。foldRight与foldLeft相当于非对易关联操作吗?

其中一位学生坚持认为,这些操作员只需要关联。所以这个属性应该适用于像函数组合和矩阵乘法这样的操作。

至于我可以告诉关联的操作,是不可交换不会产生相同结果foldLeftfoldRight除非z是中性的,并且操作以这样的方式积累的操作数的顺序保持不变。在一般情况下,IMO的操作必须是可交换的。

list.foldLeft(z)(operation) == list.foldRight(z)(operation) 

所以,foldLeftfoldRight等同应该operation是同时联想和交换还是不够operation进行关联?

回答

4

函数必须是交换和关联。

如果我们的功能是f,我们的元素是x1x4,则:

foldLeft是f(f(f(x1, x2), x3), x4)

foldRight是f(x1, f(x2, f(x3, x4)))

让我们用普通的功能,这是可交换的,但没有关联((a + b)/2 == (b + a)/2):

scala> def avg(a: Double, b: Double): Double = (a + b)/2 
avg: (a: Double, b: Double)Double 

scala> (0 until 10).map(_.toDouble).foldLeft(0d)(avg) 
res4: Double = 8.001953125 

scala> (0 until 10).map(_.toDouble).foldRight(0d)(avg) 
res5: Double = 0.9892578125 

编辑:我错过了只有关联vs只交换的船。请参阅@ jwvy关于关联但不可交换函数的字符串连接示例。

+0

好的。将引用@ jwvh的字符串连接。 – Tim

7

String级联(“ABC” +“XYZ”)是缔合性,但不可交换和foldLeft/foldRight将初始/零元件放置在所产生的串的相对端。如果该零元素不是空字符串,那么结果是不同的。

4

foldLeft是(...(z op x1)... op xn) foldRight是x1 op (x2 op (... xn op z)...) 所以op需求是可交换和关联两个是在一般情况下,相当于

1

至少有三个相关的情况下有独立的答案:

  1. op: (B, A) -> Bop: (A, B) -> B的一般情况下,如在foldLeftfoldRight的签名中,结合性和交换性都不是定义。

  2. 如果B >: Azop: (B, B) -> Bop双面身份然后List[A]类型的所有LL.foldLeft(z)(op)返回相同的结果作为L.foldRight(z)(op)

    这是密切相关的事实,如果B >: Aop: (B, B) -> B然后,如果op是关联的,对类型的所有LList[A]L.reduceLeft(op)返回相同的结果L.reduceRight(op)

  3. 如果B >: A,和op: (B, B) -> B既是缔和交换然后List[A]类型的所有LB类型的zL.foldLeft(z)(op)返回相同的结果作为L.foldRight(z)(op)