既然Control.Monad.Error
已被弃用,并且Control.Monad.Except
占据了至高无上的地位,很多在线资源都无法实现,并且仍会展示如何使用Error
的示例。< / p>
那我该如何转向
instance Error MyError where
noMsg = ...
strMsg = ...
使用Except
进行某些操作。只需将Error
替换为Except
并不起作为Except
需要其他类型参数
我知道Except
中不存在那些确切的方法,那么替代方法是什么?
答案 0 :(得分:11)
简短回答是:完全取代Error
,将ErrorT
替换为ExceptT
,只要您不使用Error
,事情就会继续有效s方法,fail
(现在有不同的定义),或do
符号中的失败模式匹配。
旧Control.Monad.Error
系统与新Control.Monad.Except
系统之间的本质区别在于新系统对错误/异常类型强加 no 类限制。
我们发现,根据多态,使用任何错误/异常类型的能力比自定义字符串错误消息转换的有点hacky能力更有用。
所以班级Error
已经消失了。
作为副作用,fail
的{{1}}现在已从基础monad中解除。这也会改变ExceptT
表示法中失败模式的影响。
旧的定义是:
do
我认为相当于
fail msg = ErrorT $ return (Left (strMsg msg))
如果您仍然需要此行为,则可以改为使用
fail msg = throwError (strMsg msg)
(throwError yourIntendedErrorValue
可以使用throwE
(即transformers
)而不是Control.Monad.Trans.Except
。
旧mtl
模式匹配失败将适用于
do
当动作实际返回do
Just x <- myErrorTAction
...
时。这更尴尬,但你可以,例如将其替换为明确的Nothing
匹配(基本上是让它失望):
case
@DanielWagner建议以下内容以避免额外缩进:
do
y <- myErrorTAction
case y of
Nothing -> throwE ...
Just x -> do
...
删除do
x <- myErrorTAction >>= maybe (throwError ...) return
...
也消除了Error
命名不一致的需要:大多数变换器遵循Control.Monad.Error
是变换器名称的规则,{{1 }}是SomethingT
的类型别名。旧的Something
打破了这一点,因为SomethingT ... Identity
类被用于完全不同的东西。
在新系统ErrorT
中,与其他变形金刚一样。