Doing IO in foldr repeats lines?

Andreas Rossberg rossberg@ps.uni-sb.de
Tue, 23 Jan 2001 15:04:40 +0100


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. ::