NOTE I'm just trying to understand what's happening in this particular piece of code shown below. I know this might not be the best way to solve the problem.
I'm trying to use the lazy Writer
monad with a memozied fibonacci function to count the number of times the function is called. The function returns the correct value fast but the Writer
environment never returns and doesn't use any CPU or memory.
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.
Can someone explain what's going on? Why doesn't the environment return a value?
EDIT
The infinite list [0..]
is not the problem here. I've tried replacing it by a limited list such as [0..10]
or [0..n]
but the problem still persists.
If the infinite list was the problem it would've been a very memory-intensive computation and that's why I mentioned above that it doesn't consume any CPU or memory which is what confuses me.
I believe that, due to laziness, there's a deadlock occurring somewhere somehow when evaluating the nodes of the fib
function.
fib
tries to execute the monadic actionfibs
, which eventually tries to evaluate itself so it gets stuck. And because this is done using graph reduction, no actual computation is taking place just a node is being blocked on itself. Due to purity the compiler doesn't need to keep traversing this infinite cycle in the graph, so it doesn't, which explains the cpu/memory usage thing. – is7s