@djinn MonadError e m => m()

时间:2014-01-07 10:38:39

标签: haskell monads

是否可以提供类型

的表达式
MonadError e m => m ()

会引发错误,可以使用catchError处理?请注意,缺少Error e要求。

fail下使用catchError创建的错误在什么情况下可以处理?什么可能导致fail没有被catchError抓住?这些情况在GHC发布方面有何变化? (在基础4.3中,行为发生了变化mention。)

此问题的背景是一段较大的代码(Igor2函数nomatch),其中使用fail "some message"创建的错误经过catchError并终止程序,但用fail替换throwError undefined调用会导致错误被捕获。当然throwError undefined是一个丑陋的黑客,这个问题旨在了解背景和正确的解决方案。

1 个答案:

答案 0 :(得分:3)

这里有几个不同的问题,所以我会按顺序完成它们。

MonadError e m => m ()

上述问题是,如果e没有受到任何限制,则无法为e创建throwError类型的值throwError undefined 。所以不,上述类型引发错误的唯一有效值需要包括

Error e

这是一个警察(并不是很有用)。 e约束允许您通过提供从字符串构造类型e的值的机制来保留MonadError摘要。

  

在什么情况下可以使用catchError处理失败时创建的错误?什么可能导致失败没有被catchError捕获?

这完全取决于有问题的monad。 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的第一行,MonadError使用IO的{​​{1}}实例,第二行使用MonadError的{​​{1}}实例}。 Either String导致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不同。

  

这些情况在GHC发布方面有何变化? (有人提到基础4.3中的行为发生了变化。)

基数4.3的变化是指fail monad中fail的工作原理。在以前的版本中,Either返回了一个fail值,该值可以在Left中捕获但在4.3中使用error并触发必须在{{{}处理的异常1}}(例如catch)。

Igor2中的问题听起来像它使用catchError monad并假设IO应该使用Either时的旧行为(如果有fail则简单throwError没有合适的Left实例)。