haskell - Control.Exception.Safe,为什么 exceptT 和 Either 的行为如此不同?

标签 haskell exception error-handling either

我正在尝试将 Control.Exception.SafeControl.Monad.Except 一起使用。

throwString "Foo" :: Except String a
-- error, no instance for `MonadTrow Identity`

好吧,显然 Except 将其错误抛出到变压器堆栈中的底层 monad 中? 但这是为什么呢? Except 基本上不就是为了处理异常而设计的吗?为什么会有这种奇怪的行为?为什么不是 Left "Foo"

的等价物

编辑:

可以进一步说明我的问题:

我认为 ExceptT e m aEither e a 的关系就像 ReaderT a m ba -> b 的关系一样。 Control.Monad.Except.throwErrorcatchError 的工作方式与 Control.Exception.Safe.throwcatch 完全相同> 用 Eather e a 来做。 然而,当它们应用于 Except e a 时,它们的工作方式突然不同了。

当我想在 monad 转换器的上下文中使用 Control.Exception.Safe 提供的 Either e a 行为时,我该怎么办?

我的背景是,我“在 48 小时内为自己编写一个方案”,并希望概括错误(使用 MonadThrow),以便我可以用它做一些 IO 操作。

编辑2:

示例:

data CountError = CountError deriving (Show, Except)

x :: String -> ExceptT CountError (Writer [String]) Int
x str = do { lift $ writer (length "str", return str); }

现在,这将计算字符数并收集写入器中的字符串。这可以根据您的需要延长。该错误可能表示“字符串中的字符错误”,或“字符太多”,或其他任何信号。

y :: MonadThrow m => m a
y = throw CountError

这是一个非常普遍的异常,我可以将其用于与任何其他类型的异常组合,但 ExceptT 除外:

y >> x
-- No instance for MonadThrow Identity
-- But what I want is (Left CountError, [])

最佳答案

Ok, so apparently Except throws its error into its underlying monad in the transformer stack?

正如我在评论中所说: except 不会“将错误扔到底层 monad 中”,这正是 MonadThrow 实例正在做的事情。

But why is that?

MonadThrow 的实例不能将所有类型 e 的 String 异常抛出到 ExceptT e 中,而不是只为 ExceptT String 提供一个实例> 看来作者在下一个更高的 monad 上引发了异常。

Isn't Except basically designed to handle exceptions?

事实上,Except 的设计目的是允许在特殊情况下发生故障。

作为迂腐的人,我将其称为异常的替代方案。一个 monad 管道了另一种返回概念(错误情况)并称自己为“Except”,实际上并不意味着正在使用任何典型的异常选项,例如低级堆栈展开。

Why this weird behavior?

因为 MonadThrow 实例是从 Control.Monad.Throw 重新导出的:

-- | Throws exceptions into the base monad.
instance MonadThrow m => MonadThrow (ExceptT e m) where
  throwM = lift . throwM

Why not the equivalent of Left "Foo"

因为这样实例就必须是 ExceptT String 而不是 ExceptT e。或者,这就是为什么我认为异常(exception) (Edward Kmett) 的作者决定采用这种设计。

相反,请考虑使用 Control.Monad.Except.throwError ,它可以实现您想要的功能。

What do I do, when I want to use the behaviour of Either e a that is supplied by Control.Exception.Safe but in the context of monad transformers?

您在谈论什么“Either e a”行为?您正在寻找的内容与throwError有何不同?据我所知,您正在寻找不必要的额外抽象层。

关于haskell - Control.Exception.Safe,为什么 exceptT 和 Either 的行为如此不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48029125/

相关文章:

haskell - 为什么 Prelude.drop 比普通的快?

Haskell 堆栈 - 允许更新启用并且不会关闭?

haskell - .~ 的 Monadic 版本(Haskell)

python - 我应该如何在 Python 中捕获 `with open(filename)` 引发的异常?

java - Java 中 SQL 连接的问题

c# - C#-验证时突出显示错误的控件

python - 类型错误: __init__() got an unexpected keyword argument 'checkpoint_callback'

haskell - 抽象记录还是记录接口(interface)?

Python Django 异常中间件用于不在 View 中的异常

php - 隐藏Codeigniter错误并回显自定义错误