
Bulat Ziganshin-2 wrote:
Hello Matthew,
Sunday, July 23, 2006, 10:35:41 AM, you wrote:
sequence $ [ reffill b s | s <- [0..(fi temits)-1], b <- [0..(fi
nc)-1]]
Now thats interesting. I can see that this function is more appropriate since I do not need to retrieve data from the IO monad, but what I don't understand is why it's actually faster. I will give it a try and test it on a large set to see if things change.
let's see at their (possible) definitions:
sequence [] = return [] sequence (action:actions) = do x <- action xs <- sequence actions return (x:xs)
sequence_ [] = return () sequence_ (action:actions) = do action sequence_ actions
sequence_ is TAIL-RECURSIVE function. moreover, when it's inlined, the result is what just all the action in list are sequentially performed without creating any intermediate data structures. so, using sequence_ in above example is equivalent to implementing this cycle by hand.
but when you use sequence, result of each action is saved and list of all results is built. this list requires 12 bytes per element, so you got 600 mb of garbage and much slower execution
Thanks Bulat, that was concise and explains it well. Now the question is what do I do if I do have data building up in the monad. ie if I want to generate a large list of doubles in the IO monad? Moreover those doubles depend in some way on data wrapped up or generated in the monad. It seems that building a list of IO actions in advance is a bad idea.
Perhaps the implementaton with the tail call will work in this case if an extra accumulator argument is added.
-- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- View this message in context: http://www.nabble.com/Why-Haskell--tf1986013.html#a5458595 Sent from the Haskell - Haskell-Cafe forum at Nabble.com.