I’ve defined a custom error type that I want to use with the Error monad. For the sake of example, here’s a dummy one:
newtype CustomError = CustomError String
instance Error CustomError where
strMsg = CustomError
I’d like to define a throwCustomError function that works like throwError, but instead of just throwing the string it’s given, it uses it to create a CustomError and then throws that. This definition works:
-- | Throws a 'CustomError' containing the given error message.
throwCustomError msg = throwError $ CustomError msg
However, I’d like to add a type declaration, mainly so that Haddock will include the function’s description in the generated documentation. If I use :t in GHCI, it tells me that the type of this function is MonadError CustomError m => String -> m a, and that makes sense to me, but if I write
throwCustomError :: MonadError CustomError m => String -> m a
GHC complains about a “non-variable type argument” and tells me I have to use -XFlexibleContexts to permit it. Why do I have to use a language extension to declare a function of this type, when I can define a function of this type without using any language extensions? Is there a way to declare this function’s type without using language extensions?
On a separate note, I originally tried defining the function as
throwCustomError = throwError . CustomError
but GHC tells me “No instance for (MonadError CustomError m0) arising from a use of throwError“. I don’t quite understand why this definition isn’t equivalent to the other one; they both mean the same thing as far as I can see.
Taking a step back: should I even bother defining this function? Or should I just write throwError $ strMsg "foo" when I want to throw an error? (Currently I have throwError "foo" throughout my code, so I need to change those lines either way.)
Since you’re using the
Errormonad, you’re already relying on extensions, most notablyMultiParamTypeClassesandFunctionalDependencies, so I’m not sure that there is any point in trying to keep your code extension-free.There are some extensions which have some potentially nasty side-effects (e.g.
IncoherentInstances), and there’s certainly a point to keeping usage of those to a minimum, but extensions likeFlexibleContextsare completely harmless.