I have the following monad transformer for dealing with errors in Haskell.
instance (Monad m, Error e) => Monad (EitherT e m) where
return = EitherT . return . return
m >>= k = EitherT $ do
a <- runEitherT m
case a of
Left l -> return (Left l)
Right r -> runEitherT (k r)
fail = EitherT . return . Left . strMsg
It works fairly well, as I can instantiate Error with a custom class and have a pretty flexible means by which to handle errors.
fail is a bit silly, though, because it is type String -> EitherT e m, and the String restriction can be an annoying way to create errors. I end up with a whole lot of:
instance Error BazError where
strMsg "foo" = FooError -- oh look we have no error context
strMsg "bar" = BarError -- isn't that nice
What I'd like to do is create a new function, like fail, that is of type a -> e so that I can remove the (Error e) restriction. fail is especially convenient when the monad stack gets large, like when I end up with
EitherT BazError (StateT [BazWarning] IO) Foo
Is there a way to create a function that has the same behavior as fail with a less restrictive type? Or is fail implemented using deep haskell dark magic?
Well, fail is called if you have a pattern-match failure in a do block, like if you have Just x <- something and something's result is Nothing. Apart from that, fail is an ordinary function.
For the problem with strMsg "foo" = FooError etc, does throwError offer a nicer interface for your use case?
This article may be useful: http://blog.ezyang.com/2011/08/8-ways-to-report-errors-in-haskell-revisited/
Your EitherT is already in the standard library and called ErrorT. See the documentation: http://hackage.haskell.org/packages/archive/mtl/latest/doc/html/Control-Monad-Error.html#t:ErrorT
fail is a historical curiosity now, and may considered a design flaw, along with lack of Functor a => Monad a constraint. It is only a controversial feature to handle failed pattern matches in do notation.
throwError :: MonadError e m => e -> m a
is the most common replacement for fail, but more are available (see the article).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With