【发布时间】:2016-01-19 16:21:30
【问题描述】:
这是一个打印前 40 个斐波那契数的小程序三次 -
module Main where
fib :: Int -> Int
fib 1 = 1
fib 2 = 1
fib n = fib (n-1) + fib (n-2)
main :: IO ()
main = run >> run >> run
where
run = mapM_ (print . fib) [1..40]
如果我用ghc Main.hs编译它,那么“运行”的计算部分被GHC保存,所以执行run的时间与运行一次大致相同。这真是一个惊喜!我的印象是一元效应不会像这样自动记忆。
另外,如果我用ghc -O2 Main.hs 编译它,那么记忆就会丢失。 (至少在我的机器上使用 ghc 7.10.3)
我如何预测什么时候会被记住?某处是否有一些记录在案的经验法则?这怎么和unsafePerformIO之类的玩?
【问题讨论】:
-
FWIW:
run即使在我的机器上使用-O2也只评估一次(所以我没有观察到您的“缓存丢失”行为)。 -
@DanielWagner 有趣!你在哪个 GHC 版本上?我在 GHC 7.10.3 上。
-
@MathematicalOrchid 是的!
-
@AnupamJain 7.10.2 -- 我很惊讶这种行为在不同的版本中发生了变化!
-
@DanielWagner:可以确认,Windows 上的 GHC 7.10.3 使用堆栈。
-O2提供了更好的fib,但所有三个run都重新计算了它。ddump-simpl显示--O0将run :: IO ()向外浮动,而-O2将其内联到mainK :: Int# -> State# ... -> (State#, () #)。
标签: performance haskell monads ghc memoization