Haskell中函数调用的优化

Posted

技术标签:

【中文标题】Haskell中函数调用的优化【英文标题】:Optimization of Function Calls in Haskell 【发布时间】:2011-08-30 12:27:51 【问题描述】:

不知道这个问题到底要谷歌什么,所以我将它直接发布到 SO:

    Haskell 中的变量是不可变的 纯函数应该为相同的参数产生相同的值

从这两点可以推断,如果您在代码中调用somePureFunc somevar1 somevar2 两次,则只有在第一次调用期间计算值才有意义。结果值可以存储在某种巨大的哈希表(或类似的东西)中,并在随后调用该函数时进行查找。我有两个问题:

    GHC 真的会做这种优化吗? 如果是这样,在重复计算实际上比查找结果更便宜的情况下,会发生什么行为?

谢谢。

【问题讨论】:

我怀疑你是否需要一个“巨型哈希表”,除非你想优化两个独立变量发生两个具有相同值的情况 - 但这可能不值得付出努力,而且事实上更没用该函数参数不会被频繁地完全评估(即,您无法检查它们是否实际上相同,至少不会浪费您想要使用的宝贵计算时间)。 查看此非常见问题解答***.com/questions/5898162/… 【参考方案1】:

GHC 不自动执行memoization。请参阅Common Subexpression Elimination 上的 GHC 常见问题解答(不完全相同,但我猜推理是相同的)和this question 的答案。

如果您想自己做 memoization,请查看Data.MemoCombinators。

另一种看待记忆化的方法是利用惰性来利用记忆化。例如,您可以根据自身定义一个列表。下面的定义是所有斐波那契数的无限列表(取自Haskell Wiki)

fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

因为列表是延迟实现的,所以它类似于预先计算(记忆)以前的值。例如fibs !! 10 将创建前十个元素,这样fibs 11 会更快。

【讨论】:

【参考方案2】:

保存每个函数调用结果(参见hash consing)是有效的,但可能会造成巨大的空间泄漏,并且通常还会大大降低您的程序速度。检查表中是否有某些内容通常比实际计算要花费更多。

【讨论】:

以上是关于Haskell中函数调用的优化的主要内容,如果未能解决你的问题,请参考以下文章

从 Rust 调用动态链接的 Haskell 代码

c_cpp 类似Haskell的部分函数调用C ++ 11

操作list的几个基础函数

函数返回与函数参数中的 Haskell 模式匹配

在 Haskell 中评估函数 a -> () 有啥规则?

Haskell中的重载内置函数