我正在阅读有关如何优化Haskell代码的内容,并遇到了有关Single-constructor datatypes in GHC的注释。
节选:
GHC喜欢单构造函数数据类型,例如元组。将单构造函数数据类型传递给严格函数时,可以将其解压缩。例如,给定此功能:
f (x,y) = ...
GHC的严格性分析器将检测到f在其参数中是严格的,并像这样编译函数:
f z = case z of (x,y) -> f' x y f' x y = ...
其中f称为包装器,f'称为工作器。包装器到处都是内联的,因此,例如,如果您有这样的对f的调用:
... f (3,4) ...
这最终将被编译为
... f' 3 4 ...
元组已完全优化。
这是否意味着我应该遍历程序并将所有函数参数包装到一个元组中?无论如何,当元组被展开时,我真的看不到这是一种优化。
这是INLINE
编译指示的替代方法吗?我应该同时使用吗?只有一个?更好吗?
答案 0 :(得分:11)
无论如何,当元组被展开时,我真的看不到这是一种优化。
那是的优化:元组被解包。 IOW,最终运行的程序根本不会包含任何元组,而只包含两个参数的函数调用。
人们可能还会对此表示更悲观的说法:从头开始,元组本质上对性能不利。这是因为tuple参数需要三个指针间接寻址:整个tuple的thunk,fst
元素的thunk和snd
元素的thunk。因此,原则上,为了提高性能,将数据包装到元组中是一个非常糟糕的主意。 (最好将其放在具有严格字段的data
结构中。)当然,除非您确实确实需要在所有这些地方都懒惰。
然而,这就是引用的全部内容,实际上,在GHC中使用元组通常还是可以的,因为如果可以证明不是,则通常可以优化间接寻址实际需要的。