[Haskell-cafe] Re: How to combine Error and IO monads?

J. Garrett Morris trevion at gmail.com
Thu Dec 7 14:12:48 EST 2006

On 12/7/06, Cat Dancer <haskell-cafe at catdancer.ws> wrote:
> On 12/7/06, apfelmus at quantentunnel.de <apfelmus at quantentunnel.de> wrote:
> I'm sure from a single example I could understand what was going on
> and elaborate from there.
> Let's say I want to get a line from the user, and either return an
> integer or an error string using ErrorT.
>   import Control.Monad.Error
>   import Control.Monad.Trans
>   foo :: ??

foo :: ErrorT String IO Int

if you're going to use this very often, you can use a line like

type M = ErrorT String IO

and then foo :: M Int

>   foo = do  -- something like this?
>     a <- getLine

Since ErrorT String IO Int is not the same as IO, you can't use IO
operations directly.  In this case, you want:

<     a <- lift getLine

>     if length a == 1
>       then return 123
>       else throwError "not a single character"

This is all fine

>   main = do
>     r <- ?? foo ??

You want:

<     r <- runErrorT foo

and then this will behave as expected:

>     print r -- prints Left "not a single character" or Right 123 ?

Your foo operation is in a monad which wraps IO.  lift allows IO
operations inside that wrapper, and runErrorT removes the wrapper.
The same basic pattern works for other wrappers (like StateT or ListT)
or combinations of wrappers (like StateT Int (ErrorT String IO))


It is myself I have never met, whose face is pasted on the underside of my mind.

More information about the Haskell-Cafe mailing list