{- A moderately evil hack to help us lazify IO actions. Tom Moertel 2007-02-27 -} module LazyIO ( LazyIO(), runLazy, deferIO ) where import System.IO.Unsafe (unsafeInterleaveIO) newtype LazyIO a = LazyIO { unLazyIO :: IO a } instance Monad LazyIO where return = LazyIO . return ma >>= fmb = LazyIO $ runLazy ma >>= unLazyIO . fmb deferIO :: IO a -> LazyIO a deferIO = LazyIO runLazy :: LazyIO a -> IO a runLazy = unsafeInterleaveIO . unLazyIO {- Other formulations of Lazy-IO monads: http://programming.reddit.com/info/18mm1/comments/c191v9 -} {- Demo of unsafeness. Uncomment the unsafeDemo function and compile with the following recipe: $ ghc --make -o unsafedemo -main-is LazyIO.unsafeDemo LazyIO.hs Then run the program on the input "1\n2\n": $ { echo 1; echo 2; } | ./unsafedemo # Output is: ["1","2"] The LazyIO monad allows the ordering guarantees of the IO monad to be violated. In this case, the second call to getLine was allowed to execute before the first. Had we not used laziness, the output would have been ["2","1"]. unsafeDemo = print =<< runLazy getOneTwo where getOneTwo = do one <- deferIO getLine two <- deferIO getLine return [two, one] -}