[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 ??
< 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