是否可以给出一个类型的表达式
MonadError e m => m ()这会引发一个错误,可以用catchError来处理吗?注意没有Error e要求。
在什么情况下,用fail创建的错误可以用catchError来处理?什么能导致fail不被catchError捕获?在释放GHC方面,这些情况发生了什么变化?(有一个提及,它的行为在基4.3中发生了变化。)
这个问题的背景是一段更大的代码(Igor2函数nomatch),其中使用fail "some message"创建的错误通过catchError传递并终止程序,但是将fail调用替换为throwError undefined会按预期捕获错误。当然,throwError undefined是一个丑陋的黑客,这个问题的目的是了解背景和正确的解决方案。
发布于 2014-01-07 11:08:49
这里有几个单独的问题,所以我将按照顺序来讨论它们。
MonadError e m => m ()上面的问题是,如果e不以任何方式受到约束,就不可能创建e类型的值,这是throwError所需要的。因此,不,上述类型引发错误的唯一有效值需要包括
throwError undefined这是一种合作(也不是很有用)。Error e约束允许您通过提供一种机制来从字符串构造e类型的值,从而保留e抽象。
在什么情况下,使用catchError可以处理由fail创建的错误?什么能导致不被catchError捕捉到的失败?
这完全取决于所讨论的单一因素。不同的MonadError实例可能对fail有不同的实现,因此没有通用的答案。换句话说,fail触发的错误不能由catchError来处理,除非您使用的是特定的MonadError实例。例如:
{-# LANGUAGE FlexibleContexts #-}
import Control.Monad.Error
example :: (Error e, MonadError e m) => m String
example = fail "This is a failure" `catchError` const (return "Error was caught")
main = do
example >>= putStrLn
either putStrLn putStrLn example在main的第一行中,example使用IO的MonadError实例,第二行使用Either String的MonadError实例。fail在IO中会产生一个可捕捉的错误,但在Either中不会产生错误,所以程序输出。
Error was caught
*** Exception: This is a failure但是,如果我们将example替换为
example :: (Error e, MonadError e m) => m String
example = throwError (strMsg "This is a failure")
`catchError` const (return "Error was caught")然后我们得到所需的输出。
Error was caught
Error was caught这对于MonadError的任何(有效)实例都是一样的,这与fail不同。
在释放GHC方面,这些情况发生了什么变化?(有人提到,基础4.3中的行为发生了变化。)
基4.3中的变化是指fail在Either monad中的工作方式。在以前的版本中,fail返回了一个Left值,这个值可以用catchError捕获,但是在4.3中,在它使用error之后,会触发一个必须在IO中处理的异常(例如,catch)。
Igor2中的问题听起来像是它使用Either monad,当它应该使用throwError (或者如果没有合适的Error实例的话,简单地使用Left )时,它假设fail的旧行为。
https://stackoverflow.com/questions/20969456
复制相似问题