[Haskell-cafe] Fighting the monad stack, MonadIO

Adam Smyczek adam.smyczek at gmail.com
Thu Apr 10 14:53:06 EDT 2008

Thanks a lot for all explanations!

It looks like 'ioAction' is the key to the solution
and if the Browser module did not provide/expose
this function, no IO actions could be run inside
the BrowserAction monad?

If yes, is this a general concept/pattern
how to hide functionality of a underlying monad,
in this case hide IO entirely?


On Apr 10, 2008, at 11:02 AM, Judah Jacobson wrote:

> On Thu, Apr 10, 2008 at 7:50 AM, Adam Smyczek  
> <adam.smyczek at gmail.com> wrote:
>> For a small webapi binding I try to implement a session like monad
>>  by building a stack including BrowserAction from Network.Browser
>>  module as following:
>>  newtype RBAction a = RBAction
>>     { exec :: ErrorT String (StateT RBState BrowserAction) a }
>>     deriving (Functor, Monad, MonadState RBState)
>>  I would like the RBAction to implement MonadIO as well,
>>  but fight with the liftIO function for hours now, without success.
>>  Any idea how the implementation of liftIO could look like?
> In order to make a stack of monads an instance of MonadIO, you need to
> be able to run IO actions in the innermost monad (BrowserAction).
> Ideally, that monad itself would be an instance of MonadIO; maybe the
> authors of HTTP didn't do so because it would add a dependency on the
> mtl package (which defines the MonadIO class).
> Luckily, though, Network.Browser provides
> ioAction :: IO a -> BrowserAction a
> which is exactly what you need to write the MonadIO instances  
> yourself.
> -- Solution #1 --
>> instance MonadIO BrowserAction where
>>     liftIO = ioAction
> Then you can add MonadIO to the deriving clause for RBAction.
> -- Solution #2 --
>> instance MonadIO RBAction where
>>    liftIO = RBAction . lift . lift . ioAction
> This pulls IO actions manually through the stack of transformers.  It
> might be better because if the HTTP package ever provided its own
> instance of MonadIO BrowserAction, that would conflict with #1.
> Hope that helps,
> -Judah

More information about the Haskell-Cafe mailing list