
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
-- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Well lo and behold I also need decent performance when doing a lot of IO actions that do not discard their arguments. For example suppose I want to generate a huge array of random numbers. I certainly don't want to multiply my memory requirements by the factor of 12 you mention. It doesn't seem too hard, however to devise tail recursive functions that fit the bill. For example suppose I define a function that repeatedly applies an IO action like this repIO act llist = let repIO' iolact (act) (x0:xl) = do lact <- iolact z <- act x0 repIO' (return (z:lact)) act xl repIO' iolact act [] = iolact nullio = return [] in repIO' nullio (act) llist I can then create a list of random numbers in the IO monad like this main = repIO (\x -> (randomIO :: IO Double)) [1..10] >>= print Of course this one reverses the input list indices. There must be library functions that support a more space efficient way to do these kinds of repetitive sequential IO actions. Ultimately for this little application I want to map the result to an array inside the IO monad. It looks like I have to create the list first. Suppose however I pulled the random value out of the IO monad using unsafePerformIO separately for each index. Lazy evaluation would cause the IO action to occur in an unspecified order. But for the randomIO function I don't really care what order it's called in. Would this have any other unforseen consequences? Are there cases where the IO action would only be partially evaluated, messing up the random number generator? -- View this message in context: http://www.nabble.com/Why-Haskell--tf1986013.html#a5498263 Sent from the Haskell - Haskell-Cafe forum at Nabble.com.