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

Haskell中foldr/foldl作用于二元组时为何忽略首个元组元素?

问题描述

我在测试中观察到如下现象:

foldr (+) 0 (3,7)
7
foldl (+) 0 (3,7)
7

测试环境版本信息:

ghci --version 
The Glorious Glasgow Haskell Compilation System, version 9.2.2

请问上述运行结果是否为符合语言设计的预期行为?该行为背后的设计原理是什么?


解答

这个运行结果完全是符合Haskell语言设计预期的正常行为,不是编译器bug。
背后的核心设计逻辑和Foldable类型类的二元组实例规则直接相关:

  • Haskell中二元组类型(a,b)的Foldable实例,是将二元组定义为「携带一个固定类型附加注解的单元素容器」:容器内参与折叠遍历的元素只有第二个字段,第一个字段属于容器本身附带的上下文信息,折叠时会被直接忽略。
  • 这个设计的合理性来自类型约束:二元组的两个字段类型可以完全无关,比如(String, Int)类型的二元组,第一个字段是字符串,根本无法和数值类型的初始值、累加值做加法运算。如果要求折叠操作同时处理两个字段,根本无法写出类型通用的折叠实现。

你可以用几个简单的测试验证这个规则:

-- 第一个字段不管是什么值,都不会参与折叠计算
foldr (+) 100 (9999, 5)  -- 结果为105,即100 + 5
foldl (*) 2 ("任意字符串", 4) -- 结果为8,即2 * 4

回到给出的测试用例:(3,7)的第一个字段3会被折叠逻辑直接跳过,不管是右折叠foldr还是左折叠foldl,都只会取第二个字段7和初始值0做加法运算,0 + 7 = 7,因此两个表达式的输出结果一致。
如果需要对二元组的两个字段同时做聚合计算,不能直接使用通用的foldr/foldl,需要手动取两个字段完成计算,或者使用适配二元组的专用运算函数。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 16:48:53