Haskell 如何将'throwM'与'Except'连用?
有一个包的特点是单子 这个monad转换器扩展了monad,使其能够抛出异常 有一个具有此效果的软件包 抛出异常 所以看起来这两个人应该配合得很好。然而:Haskell 如何将'throwM'与'Except'连用?,haskell,Haskell,有一个包的特点是单子 这个monad转换器扩展了monad,使其能够抛出异常 有一个具有此效果的软件包 抛出异常 所以看起来这两个人应该配合得很好。然而: λ runExcept $ throwM Overflow <interactive>:46:13: error: • No instance for (MonadThrow Data.Functor.Identity.Identity) arising from a use of ‘throwM’
λ runExcept $ throwM Overflow
<interactive>:46:13: error:
• No instance for (MonadThrow Data.Functor.Identity.Identity)
arising from a use of ‘throwM’
• In the second argument of ‘($)’, namely ‘throwM Overflow’
In the expression: runExcept $ throwM Overflow
In an equation for ‘it’: it = runExcept $ throwM Overflo
λrun除了$throwM溢出
:46:13:错误:
•没有(MonadThrow Data.Functor.Identity.Identity)的实例
因使用“throwM”而产生
•在“($)”的第二个参数中,即“throwM Overflow”
在表达式中:runExcept$throwM Overflow
在“it”的方程式中:it=runExcept$throwM Overflo
我知道我可以用单子。但无论如何,我想
了解发生了什么。我不太熟悉monad transformers。编译器通过以下方式推断类型:
- 由于
,因此runExcept::Except ea->…
的参数必须是runExcept
类型Except ea
所以,throwM溢出::除了ea
是Except e a
的类型同义词Except e Identity a
所以,throwM溢出::除了标识a
- 因为
,编译器需要为匹配throwM::MonadThrow m=>e->ma
的类型找到
的一个实例,但不包括e标识throwM
- 看::
。它与任何MonadThrow m=>MonadThrow(不包括em)
的m
匹配,但该
还必须具有m
的实例MonadThrow
- 匹配
的类型,即throwM Overflow
,以及定义除了标识a
实例的类型,即MonadThrow
,编译器确定除了T m
m=Identity
- 但是等等!根据实例定义
,这个MonadThrow m=>MonadThrow(em除外)
(我们现在知道它是m
)也必须有一个Identity
实例MonadThrow
- 因此编译器会查找它,但没有找到它
- 并显示一条错误消息:“无实例
”MonadThrow标识
和throwM
实际上并不兼容。也就是说,throwM
抛出的错误与抛出的错误不同,只是包含错误。它们是两种不同的错误相关机制。要抛出与不兼容的错误,请使用。这应该起作用:
> runExcept $ throwE Overflow
Left Overflow
据我目前所知,Haskell中的错误处理环境尚未稳定到可管理的状态。我们有除了,它被推广到除了,throw
,throw
,throwIO
,throwSTM
,throwE
,throwM
,所有这些都有来自不同库和不同单子下的变体。此外,UnliftIO
的到来使事情变得更加复杂。这有点像ExceptT
将因此消失。我问了为什么没有这样的实例,我们将看看是否出现了什么。实例MonadThrow Identity
不可能存在,因为异常会去哪里?当然instance MonadThrow Except
可以。