|
|
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?
Adam
On Apr 10, 2008, at 11:02 AM, Judah Jacobson wrote:
On Thu, Apr 10, 2008 at 7:50 AM, Adam Smyczek
<adam.smyczek@xxxxxxxxx> 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
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@xxxxxxxxxxx
http://www.haskell.org/mailman/listinfo/haskell-cafe
|
|