【发布时间】:2014-04-03 11:37:27
【问题描述】:
注意 我只是想了解下面显示的这段特定代码中发生了什么。我知道这可能不是解决问题的最佳方法。
我正在尝试将惰性 Writer monad 与 memozied fibonacci 函数一起使用来计算函数被调用的次数。该函数快速返回正确的值,但Writer 环境永远不会返回并且不使用任何 CPU 或内存。
import Control.Monad.Writer.Lazy as W
fib :: Int -> Writer (Sum Int) Int
fib = let fibs = mapM fib' [0..]
fib' 0 = return 0
fib' 1 = return 1
fib' n = liftM2 (+) (fib $ n-1) (fib $ n-2)
in \n -> tell (Sum 1) >> fibs >>= return . (!!n)
Prelude W> runWriter $ fib 51
(20365011074,Sum {getSum = Interrupted.
有人可以解释发生了什么吗?为什么环境不返回值?
编辑
无限列表[0..] 不是这里的问题。我尝试用有限的列表替换它,例如[0..10] 或[0..n],但问题仍然存在。
如果无限列表是问题所在,那将是一个非常消耗内存的计算,这就是为什么我在上面提到它不消耗任何 CPU 或内存,这让我感到困惑。
我相信,由于懒惰,在评估 fib 函数的节点时,某处会出现死锁。
【问题讨论】:
-
你的猜测是正确的。对
fib的每次调用都会尝试执行单子操作fibs,它最终会尝试评估自身,因此它会卡住。而且因为这是使用图形缩减完成的,所以没有实际的计算发生,只是一个节点被自己阻塞了。由于纯度,编译器不需要继续遍历图中的这个无限循环,所以它不需要,这解释了 cpu/memory 使用情况。
标签: haskell monads memoization writer-monad