[Haskell] Using MonadError within other Monads
tpledger at ihug.co.nz
tpledger at ihug.co.nz
Thu Jan 5 00:03:55 EST 2006
(In reply to
http://www.haskell.org/pipermail/haskell/2005-December/017109.html
)
One of the key things about those nested monads is that
*often* you
don't have to write things like
return $ throwError msg
but can simply write
throwError msg
because the nest has all the features of its components.
The IO monad doesn't participate fully in this, but the
liftIO
function (from the MonadIO class) serves as an adapter.
> import Control.Monad.Error
> f () = do n <- liftIO readLn
> when (n == 2) (throwError "2-char string")
> sequence (replicate n (liftIO getChar))
> `catchError` (throwError . ("g Error: "++))
(Pay no attention to the () parameter behind the curtain!
I'm dodging
the monomorphism restriction, and don't want to give an
explicit type
signature.)
The inferred type is
f :: (MonadError [Char] m, MonadIO m) => () -> m [Char]
i.e. it's usable for any nest of monads that provides the
MonadError String
and MonadIO features.
Now, how to run it? Your type signatures of the form
IO (Either String String)
are very reminiscent of the ErrorT monad transformer
newtype ErrorT e m a
= ErrorT {runErrorT :: (m (Either e a))}
with IO as m and String as e and a. So, let's test f in
ErrorT String IO.
*Main> runErrorT (f ()) >>= print
0
Right ""
*Main> runErrorT (f ()) >>= print
2
Left "I don't like strings with 2 characters."
*Main> runErrorT (f ()) >>= print
4
Too
Right "Too\n"
Regards,
Tom
More information about the Haskell
mailing list