Adapting Error to Except

末鹿安然 提交于 2020-01-12 01:39:08

问题


Now that Control.Monad.Error is deprecated, and Control.Monad.Except reigns supreme, a lot of sources online haven't caught up, and still show examples of how to use Error.

So how would I go about turning

instance Error MyError where
  noMsg  = ...
  strMsg = ...

into something using Except. Just replacing Error with Except didn't work as Except expects additional type parameters

I understand that those exact methods don't exist in Except, so what's the alternative?


回答1:


Short answer is: Replace Error by nothing at all, replace ErrorT by ExceptT, and things should continue to work as long as you don't use Errors methods, fail (which now has a different definition), or failing pattern matches in do notation.

The essential difference between the old Control.Monad.Error system and the new Control.Monad.Except system is that the new system imposes no class restriction on the error/exception type.

It was found that the ability to use any error/exception type at all, polymorphically, was more useful than the somewhat hacky ability to customize conversion of string error messages.

So the class Error has simply disappeared.

As a side effect, fail for ExceptT now is lifted from the underlying monad. This also changes the effect of failing patterns in do notation.

The old definition was:

fail msg = ErrorT $ return (Left (strMsg msg))

which I think is equivalent to

fail msg = throwError (strMsg msg)

If you still need this behavior, you can instead use

throwError yourIntendedErrorValue

(throwE works instead if you're using transformers (i.e. Control.Monad.Trans.Except) rather than mtl.)

The old do pattern matching failure would apply to things like

do
    Just x <- myErrorTAction
    ...

when the action actually returns Nothing. This is more awkward, but you could e.g. replace it with an explicit case match (essentially desugaring it):

do
    y <- myErrorTAction
    case y of
        Nothing -> throwE ...
        Just x -> do
           ...

@DanielWagner suggests the following to avoid extra indentation:

do
    x <- myErrorTAction >>= maybe (throwError ...) return
    ...

The removal of Error also eliminates the need for an inconsistency in naming that Control.Monad.Error had: Most transformers follow the rule that SomethingT is the name of the transformer, and Something is a type alias for SomethingT ... Identity. The old ErrorT broke that because the Error class was used for something entirely different.

In the new system, Except e = ExceptT e Identity, like for other transformers.



来源:https://stackoverflow.com/questions/31221410/adapting-error-to-except

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!