【发布时间】:2016-01-01 09:17:34
【问题描述】:
我有以下经常被引用的代码来计算 Haskell 中的第 n 个斐波那契数:
fibonacci :: Int -> Integer
fibonacci = (map fib [0..] !!)
where fib 0 = 0
fib 1 = 1
fib n = fibonacci (n-2) + fibonacci (n-1)
使用它,我可以进行如下调用:
ghci> fibonacci 1000
并获得几乎即时的答复。
但是,如果我修改上面的代码使其不是无点样式,即
fibonacci :: Int -> Integer
fibonacci x = (map fib [0..] !!) x
where fib 0 = 0
fib 1 = 1
fib n = fibonacci (n-2) + fibonacci (n-1)
它的速度要慢得多。在某种程度上,诸如
之类的调用ghci> fibonacci 1000
挂起。
我的理解是上面两段代码是等价的,但 GHCi 不一样。有人对此行为有解释吗?
【问题讨论】:
-
第一个定义更像
fibonacci = let k = map fib [0 ..] in \x -> k !! x。它可能会共享结果列表,而不是每次都重新计算。 -
嗯,所以我很满意正是这种“分享”(记忆)让第一个超级快。但是为什么要对第二个做同样的事情呢?
-
你在 GHCI 中运行你的代码,没有优化。尝试使用
-O2编译这两个函数,看看 GHC 是否足够聪明,可以为您解决问题。 -
更新:使用优化编译并查看生成的核心显示它是相同。为了将来参考,如果您对性能感兴趣,您必须进行优化编译!
-
@user2407038,无论如何,我认为未优化代码差异的原因很有趣。
标签: haskell memoization