给出非交换关联操作,foldRight是否相当于foldLeft?

时间:2017-02-28 18:08:47

标签: scala fold equivalent

在在线课程中,有人说foldLeftfoldRight等同于关联和交换的运算符。

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

据我所知,一个不可交换的关联操作不会产生foldLeftfoldRight的等效结果,除非z是中性且操作是在这样一种方式,操作数的顺序保持不变。在一般情况下,IMO的操作必须是可交换的。

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

那么,foldLeftfoldRight是等价的,operation应该是同时关联和可交换的还是operation是否足够关联?

4 个答案:

答案 0 :(得分:7)

String串联(" abc" +" xyz")是关联的,但不是可交换的,foldLeft / foldRight会放置初始/结果字符串两端的零元素。如果该零元素不是空字符串,则结果不同。

答案 1 :(得分: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
编辑:我错过了只有关联和仅交换的船。有关关联但不可交换的函数,请参阅@ jwvy的字符串连接示例。

答案 2 :(得分:4)

foldLeft是(...(z op x1)... op xn) foldRight是x1 op (x2 op (... xn op z)...) 所以op需要是可交换的和关联的,两者在一般情况下是等价的

答案 3 :(得分:1)

至少有三个相关案例有不同的答案:

  1. op: (B, A) -> Bop: (A, B) -> B的一般情况下,与foldLeftfoldRight的签名一样,既未定义关联性,也未定义交换性。

  2. 如果B >: Azop: (B, B) -> B的双边身份op关联然后对于L类型的所有List[A]L.foldLeft(z)(op)返回与L.foldRight(z)(op)相同的结果。

    这与以下事实密切相关:B >: Aop: (B, B) -> B如果op是关联的话,那么L List[A] L.reduceLeft(op) L.reduceRight(op) 1}}返回与B >: A相同的结果。

  3. 如果op: (B, B) -> BL同时关联且可交换,那么对于List[A]类型的所有z和{{1} } B类型,L.foldLeft(z)(op)返回与L.foldRight(z)(op)相同的结果。