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