You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell中foldl与foldr的行为差异疑问

为什么foldr和foldl用同一个lambda计算结果不同?

核心问题出在lambda的参数顺序和foldl的要求不匹配。

先明确两个折叠函数的函数参数定义:

  • foldr的函数要求是:元素 -> 累加值 -> 结果,你的lambda (\x acc -> acc + x*2)刚好符合这个顺序,所以计算正常。
  • foldl的函数要求是:累加值 -> 元素 -> 结果,你写的lambda把参数顺序搞反了,导致每次调用时把前一次的累加结果当成了x,把当前列表元素当成了acc,最终出现了幂次累加的结果。

用具体列表[1,2,3]拆解计算过程:

foldr的正确计算过程

foldr (\x acc -> acc + x*2) 0 [1,2,3]
= (\x acc -> acc + x*2) 1 (foldr ... 0 [2,3])
= (foldr ... 0 [2,3]) + 1*2
  -- 展开foldr ... 0 [2,3]
  = (\x acc -> acc + x*2) 2 (foldr ... 0 [3]) + 2*2
    -- 展开foldr ... 0 [3]
    = (0 + 3*2) + 2*2
= (6 + 4) + 2 = 12

结果是所有元素的两倍之和,符合预期。

foldl的错误计算过程(参数顺序颠倒)

foldl (\x acc -> acc + x*2) 0 [1,2,3]
-- 第一步:用初始值0和第一个元素1调用lambda,此时x=0,acc=1
= foldl ... (1 + 0*2) [2,3]
= foldl ... 1 [2,3]
-- 第二步:用当前累加值1和第二个元素2调用lambda,此时x=1,acc=2
= foldl ... (2 + 1*2) [3]
= foldl ... 4 [3]
-- 第三步:用当前累加值4和第三个元素3调用lambda,此时x=4,acc=3
= foldl ... (3 + 4*2) []
= 11

最终结果11 = 1*4 + 2*2 +3*1,也就是每个元素从右往左数的位置(从0开始)对应2的幂次乘以元素值的和——这就是你看到的奇怪结果的原因。

修正方法

把lambda的参数顺序反过来,改成(\acc x -> acc + x*2),再用foldl计算:

foldl (\acc x -> acc + x*2) 0 [1,2,3]
= foldl ... (0 + 1*2) [2,3]
= foldl ... 2 [2,3]
= foldl ... (2 + 2*2) [3]
= foldl ... 6 [3]
= foldl ... (6 +3*2) []
=12

结果就和foldr一致了。

内容的提问来源于stack exchange,提问作者placeholder223

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 05:05:39