Haskell优化器是否在范围内对重复的函数调用使用memoization?

时间:2013-02-26 08:02:39

标签: haskell optimization compiler-construction memoization

考虑这个功能:

f as = if length as > 100 then length as else 100

由于函数是纯粹的,因此很明显两个调用的长度都是相同的。我的问题是Haskell优化器是否将上面的代码转换为以下代码?

f as = 
  let l = length as
  in if l > 100 then l else 100

如果是,那么哪个级别设置启用它?如果没有,那么为什么呢?在这种情况下,内存浪费不是this answer中解释的原因,因为一旦函数执行完成,引入的变量就会被释放。


请注意,由于本地范围,这不是this question的副本,因此可能会得到截然不同的答案。

3 个答案:

答案 0 :(得分:16)

GHC现在some CSE by default,因为-fcse标志已开启。

  

默认情况下启用..启用公共子表达式消除   优化。如果您有一些,关闭此功能非常有用   你不想要共同的unsafePerformIO表达式。

然而,由于引入共享(以及因此空间泄漏)的问题,它是conservative。 CSE传递虽然获得bit better(和this)。

最后,请注意有一个完整的CSE插件。

如果您的代码可以从中受益。

答案 1 :(得分:13)

即使在这样的本地设置中,仍然存在这样的情况:共享的引入总是优化并不明显。考虑这个示例定义

f = if length [1 .. 1000000] > 0 then head [1 .. 1000000] else 0

VS。这一个

f = let xs = [1 .. 1000000] in if length xs > 0 then head xs else 0

并且你会发现在这种情况下,第一个表现要好得多,因为在列表上执行的每个计算都很便宜,而第二个版本将导致列表在内存中完全展开{{1}只有在length缩小后才能丢弃它。

答案 2 :(得分:5)

您所描述的案例与common subexpression elimination有关,而不是记忆,但似乎GHC currently doesn't do that either因为意外共享可能会导致空间泄漏。