gpt4 book ai didi

haskell - 如何使用没有 SomeException 作为参数类型的处理程序

转载 作者:行者123 更新时间:2023-12-02 03:39:37 26 4
gpt4 key购买 nike

当使用Control.Monad.Throw(即exceptions包)时,让我感到困惑的是,似乎我所有的 throw 和捕捉都必须与一起使用>一些异常

例如

value :: Either ExitCode String
value = throwM $ ExitFailure 23

在我看来,它应该可以编译,因为 throwM::(Exception e, MonadThrow m) => e -> m a,并且 ExitCode 有一个实例异常(exception)。即使这样也无法编译:

value :: Exception e => Either e String
value = throwM $ ExitFailure 23

事实上,只有当我将签名更改为 SomeException 时,它才会编译。我知道Exception类型类有一个特殊的地方

documentation for Control.Exception我可以看到他们将 catches 与签名 ArithException -> m a 或类似的处理程序一起使用的示例。我测试了它并且有效。

使用异常时这不可能吗?

编辑错误消息是:

Couldn't match type ExitCode with SomeException arising from a use of throwM

Couldn't match type e with SomeException arising from a use of throwM

最佳答案

您看到的行为来自 throwM 的类型签名:

throwM :: (Exception e, MonadThrow m) => e -> m a

以及 Either 的实例,本质上是:

MonadThrow (Either SomeException)

这使得throwM:

throwM :: (Exception e) => e -> Either SomeException a

Either SomeExceptionthrowM 可以接受任何 Exception e

但是,对于 Either ExitCodeforall e,没有 MonadThrow 实例。异常 e => 要么 e

问题在于,实际上没有一种方法可以编写对所有 e 都是多态的实例。想象一下有一个实例

Exception q => MonadThrow (Either q)

这将使throwM:

throwM :: (Exception e, Exception q) => e -> Either q a

这意味着您必须能够将any e 转换为any q,这单独使用 Exception 类型类不可能

想象一下,如果有 Either ExitCodeMonadThrow 实例。这将使 throwM 的类型签名:

throwM :: Exeption e => e -> Either ExitCode a

您可能会看到这显然是无意义的,因为有许多 Exception 实例无法强制转换为 ExitCode。 (如果您不相信我,请尝试编写具有该类型签名的函数!)

如果您只想Either 的短路异常行为,请考虑:

  1. 只需使用 Left 而不是 throwM,并使用 catch 进行模式匹配。如果您确实仍想使用Exception,则可以使用fromException尝试将SomeException强制转换为Exception 您选择的实例。
  2. 您可以使用异常包,只要您必须假设异常可以是任何实例(SomeException),捕获仍然有效
  3. 如果您想要某种具有捕获能力的多态接口(interface),请使用mtl中的MonadErrorExceptT

关于haskell - 如何使用没有 SomeException 作为参数类型的处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49100566/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com