On Tue, Aug 11, 2015 at 5:32 AM, Ben <hyarion@iinet.net.au> wrote:
In particular, this version of <$!> wouldn't help with the lazy IO problem described in that stackoverflow question Christopher linked earlier.

We can say more.

The version of <$!> that the SO question author himself gives as a solution to the lazy IO problem doesn't really work.

I'm referring to:
forceM :: Monad m => m a -> m a
forceM m = do v <- m; return $! v

(<$!>) :: Monad m => (a -> b) -> m a -> m b
f <$!> m = liftM f (forceM m)

and changing out <$> for <$!> in 

getLines h = lines <$> hGetContents h

With the change, all of short files get read, thanks to file buffering. Like the first 4K or so. Bad surprise when you try it with longer files.

There's a right path through lazy I/O and a wrong one. Rather than take the wrong one, better the following instead:

main = mapM_ putStrLn =<< lines <$> readFile "test.txt"

But if withFile is absolutely needed (experts only):

main = withFile "test.txt" ReadMode getAndPutLines  where
   getAndPutLines :: Handle -> IO ()
   getAndPutLines h = mapM_ putStrLn =<< lines <$> hGetContents h

-- Kim-Ee