'length' 调用是否被 GHC 重写为常量整数?

Are 'length' calls rewritten as constant ints by GHC?

只是随机思考一下我无数次的 length 调用,我突然想到编译器肯定可以告诉 any 列表的长度,这要归功于不变性和引用透明度(即使新列表是 concat-ed 来自现有已知列表/代码路径)。然后它可能会在低级代码生成期间的某个阶段将所有 length l "calls" 替换为 actual int 常量,对吗?

想知道它是否确实如此,或者我的初学者对纯函数的直觉是否遗漏了一些东西 languages/compiler。

这完全取决于所使用的数据结构。常规列表是简单的单链表:

data List a = Nil | Cons a (List a)

你可以想象 length 被这样定义:

length []     = 0
length (x:xs) = 1 + length xs

这需要 O(n) 时间到 运行,因为没有更快的方法来确定此结构的长度。

由于字符串驻留在文本文件中,它们在编译时不是常量,因此必须正常评估 length 调用。


使用包 Data.Vector 你得到 O(1) 长度的调用但失去了一些列表属性。

我认为问题是 GHC 是否在编译时将 length [1,2,3] 转换为 3。 GHC 8.0.1 是第一个进行此优化的 GHC 版本(至少在我安装的版本中)。

现在,让我们转到问题的第二部分。让我们以维基百科上 GHC 的第一个 Beta 版发布日期作为 GHC 的开始日期:1991 年 4 月 1 日。GHC 8.0.1 于 2016 年 5 月发布。因此,看来您的理论认为这是一个优化的特征在这种情况下验证了 25 年以上的编译器项目。