Reading code like the following: main = do s <- getContents let r = map processIt (lines s) putStr (unlines r) I was thinking all IO operations were lazy. But in fact it looks like getContents is lazy by design but not the whole IO stuff. Thank you all for your helpful answers, Olivier.