GHC是否复用递归函数计算结果?如何优化避免重复计算?
递归函数的GHC优化与重复计算问题
先给出问题中的递归函数定义(修正了原代码中的语法错误):
myFunction :: Integer -> Integer -> Integer -> Rational myFunction n m l | m > l = 0 | m == 1 = 1 / n ** (l - 1) | m == l = (p n l 1) * factorial (n - 1) / factorial (n - l) | otherwise = (m / n) * myFunction n m (l - 1) + ((n - m + 1) / n) * myFunction n (m - 1) (l - 1) -- 注:原代码中第二个递归调用缺失运算符与函数名,此处做合理修正;`p`函数为假设存在的辅助函数
GHC是否会复用已计算完成的值?
默认情况下不会。Haskell的惰性求值机制不会自动缓存递归子问题的计算结果,每次遇到相同参数的调用时,都会重新执行计算逻辑。只有显式使用记忆化或特定优化手段,才会让GHC复用已计算的值。
除手动消除递归外,优化重复计算的方法
- 显式记忆化:
可以使用Data.MemoCombinators这类记忆化库,或者手动用Map、数组等结构实现缓存。每次计算前先检查缓存中是否存在对应(n,m,l)参数的结果,存在则直接返回,不存在则计算后存入缓存,避免重复计算相同子问题。 - 动态规划表格迭代:
基于问题的重叠子问题特性,预先构建以l和m为维度的表格(n固定时),从m=1、m=l这类基础情况开始,按递推关系逐步填充表格,最终得到目标参数的结果。这种方式是利用动态规划的思想,通过迭代填充状态表来规避重复递归计算。 - 编译优化(有限适用):
开启GHC的-O2优化后,编译器可能会对部分简单递归做公共子表达式消除或循环展开,但对于参数组合复杂的这类递归函数,自动优化的效果非常有限,无法彻底解决重复计算问题,不能作为主要优化手段。
内容的提问来源于stack exchange,提问作者Diogenes Figueroa
相关产品推荐
相关产品推荐

