在在线课程中,有人说foldLeft
和foldRight
等同于关联和交换的运算符。
其中一名学生坚持认为这些操作员只需要联想。所以这个属性应该适用于函数组合和矩阵乘法等操作。
据我所知,一个不可交换的关联操作不会产生foldLeft
和foldRight
的等效结果,除非z
是中性且操作是在这样一种方式,操作数的顺序保持不变。在一般情况下,IMO的操作必须是可交换的。
list.foldLeft(z)(operation) == list.foldRight(z)(operation)
那么,foldLeft
和foldRight
是等价的,operation
应该是同时关联和可交换的还是operation
是否足够关联?
答案 0 :(得分:7)
String
串联(" abc" +" xyz")是关联的,但不是可交换的,foldLeft
/ foldRight
会放置初始/结果字符串两端的零元素。如果该零元素不是空字符串,则结果不同。
答案 1 :(得分:4)
该函数必须是可交换的和关联的。
如果我们的功能是f
,我们的元素是x1
到x4
,那么:
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)
至少有三个相关案例有不同的答案:
在op: (B, A) -> B
或op: (A, B) -> B
的一般情况下,与foldLeft
和foldRight
的签名一样,既未定义关联性,也未定义交换性。
如果B >: A
和z
是op: (B, B) -> B
的双边身份且op
是关联然后对于L
类型的所有List[A]
,L.foldLeft(z)(op)
返回与L.foldRight(z)(op)
相同的结果。
这与以下事实密切相关:B >: A
和op: (B, B) -> B
如果op
是关联的话,那么L
List[A]
L.reduceLeft(op)
L.reduceRight(op)
1}}返回与B >: A
相同的结果。
如果op: (B, B) -> B
和L
同时关联且可交换,那么对于List[A]
类型的所有z
和{{1} } B
类型,L.foldLeft(z)(op)
返回与L.foldRight(z)(op)
相同的结果。