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