J. Garrett Morris wrote:
This is where my favorite part of the mtl steps in: monad transformers.

I agree, the Error monad is very helpful here.

First, we'll create a transformed version of the IO monad,

Why go to the trouble of creating a new monad?
The existing ones are fine.

(While writing this, I just saw Bulat's posts. Nice!)

It would be nicest if we had MaybeT available, as in
http://www.haskell.org/haskellwiki/New_monads/MaybeT

Then you could just write:

import Control.Monad.Maybe

main = runMaybeT $ doIt `mplus` liftIO printError
where
  doIt = do
    input <- MaybeT getInput
    result <- MaybeT $ processInput input
    liftIO $ printResult result

You could simplify things if you
change the types from IO (Maybe a) to
MaybeT IO a. Then you would have:

main = runMaybeT $ doIt `mplus` liftIO printError
where
  doIt = do
    input <- getInput
    result <- processInput input
    liftIO $ printResult result

But you might want to do something more
robust with the error reporting. Then you
would do this:

import Control.Monad.Error

data MyError = InputError | OutputError | Unknown String
instance Error MyError where
 noMsg = Unknown "Oops"
 strMsg x = Unknown x

Then make the type of printError
printError :: MyError -> IO ()

and we have:

main = runErrorT $ doIt `catchError` (liftIO . printError)
where
  doIt = do
    input <- liftIO getInput >>= maybe (throwError InputError) return
    result <- liftIO (processInput input) >>= maybe (throwError
OutputError return
    liftIO $ printResult result

Again, you can simplify things if you do
change the types, using ErrorT MyError IO a
in place of IO (Maybe a), etc., and put the
throwError calls inside the functions.

main = runErrorT $ doIt `catchError` (liftIO . printError)
where
  doIt = do
    input <- getInput
    result <- processInput input
    liftIO $ printResult result

Regards,
Yitz
_______________________________________________
Haskell-Cafe mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to