Ian Lynagh wrote:
main :: IO() main = do _ <- foldl foo (return 14) ["qq\n", "ww\n", "ee\n"] putStr ""
foo :: IO Int -> String -> IO Int foo io_l s = do l <- io_l () <- putStr s io_l
prints (with both GHC and hugs):
qq ww qq ee qq ww qq
and I really don't understand why. Is the code re-evaluated every time foldl is expanded or something?
Nobody seems to have answered yet, so I try to explain it. Look at your definition of foo: it actually duplicates its argument action io_l. For the first application io_l is (return 14). Let's call that io_l0. The resulting action is io_l1 = do { l <- return 14; () <- putStr "qq"; return 14 } which is passed at the next application. The result is io_l2 = do { l <- do { l <- return 14; () <- putStr "qq"; return 14 } ; () <- putStr "ww" ; do { l <- return 14; () <- putStr "qq"; return 14 } } This can be reformulated as io_l2'= do { l <- return 14 ; () <- putStr "qq" ; l <- return 14 ; () <- putStr "ww" ; l <- return 14 ; () <- putStr "qq" ; return 14 } And so on. Finally the complete action (io_l3) is executed by running main and produces the output you observe. Hope this helps, - Andreas -- Andreas Rossberg, rossberg@ps.uni-sb.de :: be declarative. be functional. just be. ::