haskell - 如何在 Haskell 中记录所有异常?
问题描述
原标题:检查所有异常时如何处理多个异常类型实例?
我有以下导入(注意我的前奏实际上是 ClassyPrelude,它使用UnliftIO.Exception)。请注意, System.Logger 来自tinylog ,它是fast-logger之上的一个精简库。
import Prelude hiding(log)
import System.Logger hiding(log)
import qualified System.Logger as TL
以及以下功能:
logExceptions :: MonadUnliftIO m => Logger -> m a -> m a
logExceptions logger program = withException program
(\ex -> do
logIt Warn logger ["Logging exception: ", (show ex)]
flush logger
)
将 lambda 放入具有类型的本地函数可能会使其更加清晰:
logExceptions :: MonadUnliftIO m => Logger -> m a -> m a
logExceptions logger program = withException program logEx
where
logEx :: (MonadUnliftIO m, Exception e) => e -> m ()
logEx ex = do
logIt Warn logger ["Logging exception: ", (show ex)]
flush logger
这会导致以下编译错误:
* Could not deduce (Exception e0)
arising from a use of `withException'
from the context: MonadUnliftIO m
bound by the type signature for:
logExceptions :: forall (m :: * -> *) a.
MonadUnliftIO m =>
Logger -> m a -> m a
at src/FDS/Logging.hs:19:1-56
The type variable `e0' is ambiguous
These potential instances exist:
instance Exception SomeException -- Defined in `GHC.Exception.Type'
instance Exception IOException -- Defined in `GHC.IO.Exception'
instance Exception SomeAsyncException
-- Defined in `GHC.IO.Exception'
...plus four others
...plus 30 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
* In the expression: withException program logEx
In an equation for `logExceptions':
logExceptions logger program
= withException program logEx
where
logEx :: (MonadUnliftIO m, Exception e) => e -> m ()
logEx ex
= do logIt Warn logger ...
....
|
20 | logExceptions logger program = withException program logEx
|
最令人担忧的是plus 30 instances involving out-of-scope types
。我可以隐藏这些导入以稍微改善这种情况:
import GHC.Exception.Type hiding(SomeException)
import GHC.IO.Exception hiding(IOException, SomeAsyncException)
但是,通过这种方式找到所有 30 多种异常类型并将它们全部屏蔽似乎并不合理。我假设我在这里做错了什么,或者我真的需要经历并掩盖一切吗?
注意:
- 我的
logIt
函数只是log
tinylog 函数的一个薄包装 - 随意替换任何符合人体工程学的东西。
解决方案
我现在明白我的问题是Exception
参数需要具体类型,因为它是我的问题中所述的多态函数,并且没有调用站点可以将其缩小到特定类型。Catch 'em all 中描述了正确的答案!这里,就是使用具体SomeException
类型。结果代码是:
logExceptions :: MonadUnliftIO m => Logger -> m a -> m a
logExceptions logger program = withException program logEx
where
logEx :: MonadUnliftIO m => SomeException -> m ()
logEx ex = do
logIt Warn logger ["Logging exception: ", (show ex)]
flush logger
推荐阅读
- c# - 如何在同一类中更改 C# 中的起点?
- python - Tensorflow 中的梯度计算
- julia - 为什么命名 splats 在 Julia 中不起作用?
- wpf - WPF/MVVM/XAML DataGridView - 根据单元格值设置单元格背景颜色
- javascript - 当我按退格键时仍然显示错误消息(e.which ==8)
- kotlin - 如何在kotlin中执行阻塞协程调用并指定线程
- c# - 在基于文本的游戏中添加年龄错觉
- php - Laravel:本地和生产时间不匹配
- paypal - 如何使用其 API 集成支付网关并在 Aliexpress 等市场中创建支付处理?
- python - 如何在 django 中过滤查询集的多对多