两个Haskell foo函数行为是否有差异?GHC编译产物差异解析
两个Haskell
foo函数的行为与编译差异分析 函数行为是否存在差异
这两个foo函数的行为完全一致。
具体细节:
- 第一个版本里,
ws'是take 3 $ ws ++ repeat mempty的结果(必然是长度为3的列表,repeat mempty会无限补全元素),随后通过!! 0、!! 1、!! 2分别取出前三个元素; - 第二个版本直接通过模式匹配
(x:y:z:_)从take 3 $ ws ++ repeat mempty中提取前三个元素,由于take 3的结果至少有3个元素,模式匹配不会失败。
两种写法输入相同的情况下,输出完全一致,最终都会返回包含这三个元素的列表。
二进制文件大小差异的原因
这种差异并非GHC遗漏优化,而是两种写法触发了不同的优化路径:
- 第一种写法中,
ws'作为中间列表变量,三次调用通用列表索引函数!!。GHC在-O2级别下,无法完全消除!!的通用逻辑(比如边界检查、列表节点遍历的通用代码),导致目标文件保留了额外代码; - 第二种写法的模式匹配是更直接的列表解构方式,GHC可以直接将其编译为对列表前三个元素的直接提取操作,不需要保留
!!函数的通用实现,生成的代码更紧凑; - GHC优化器对不同语法结构的处理优先级和程度不同,模式匹配这种显式解构写法更容易被识别并生成精简代码,而中间变量加
!!的写法,优化器没有将其完全等价转换为模式匹配形式,最终导致目标文件更大。
你可以通过
ghc -O2 -ddump-simpl foo.hs查看GHC生成的中间简化代码,对比两种写法的编译过程差异,能更直观看到优化路径的不同。
内容的提问来源于stack exchange,提问作者Enlico
相关产品推荐
相关产品推荐

