[Haskell-cafe] combining monads with IO

Martijn van Steenbergen martijn at van.steenbergen.nl
Thu Jun 25 08:27:22 EDT 2009

Richard Silverman wrote:
> I'm puzzled by something. Suppose I have some code that does lots of IO, 
> and also occasionally refers to some global state. No problem, use 
> ReaderT for the state, combining with the IO monad. Except... since IO 
> is on the bottom, simple uses of do-notation such as "foo <- ask" work 
> in the Reader monad, and to access the IO monad, I need to lift, e.g. 
> (bar <- liftIO getLine). If my code does lots of IO, this is *very* ugly 
> -- the code is littered with lift functions!  Is there no cleaner way to 
> do this?

Not that I know of. However, you can usually group IO-statements 
together in one bigger block:

blah = do
   foo <- ask
   biz <- liftIO $ do
     bop foo
     bleep foo
   zap biz


And if there is a limited number of specific functions you need to lift 
often, you can write generalised MonadIO-based versions of these so that 
you can call them directly from the monad transformer:

   getLine :: MonadIO m => m String
   getLine = liftIO SystemIO.getLine

Assuming an appropriate MonadIO instance of ReaderT, of course.

Does that help?


More information about the Haskell-Cafe mailing list