gpt4 book ai didi

exception - 在 MonadResource 实例中捕获 IO 异常

转载 作者:行者123 更新时间:2023-12-01 12:43:04 26 4
gpt4 key购买 nike

精简版

here 中的问题相同,但在通用 MonadResource 实例中,而不是在显式 ResourceT m 中。

长版

您将如何定义一个 catch 函数:

import Control.Exception            (Exception, IOException)
import Control.Monad.Trans.Resource (MonadResource, runResourceT)

catch :: (MonadResource m, Exception e) -> m () -> (e -> m ()) -> m ()
catch = undefined

-- 'a' and 'b' are functions from an external library,
-- so I can't actually change their implementation
a, b :: MonadResource m => m ()
a = -- Something that might throw IO exceptions
b = -- Something that might throw IO exceptions

main :: IO ()
main = runResourceT $ do
a `catch` \(e :: IOException) -> -- Exception handling
b `catch` \(e :: IOException) -> -- Exception handling

我遇到的问题是:

看起来处理IO异常的唯一方法是退出ResourceT层,这让我很困扰:我希望能够在本地处理异常无需遍历 monad 转换器堆栈。

关于信息,在我的真实代码中,ab 实际上是来自Network.HTTP.Conduithttp 函数。 .

感谢您的见解。

有问题的最少代码

可通过安装了 http-conduit 库的 ghc --make example.hs 进行编译:

{-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-}
import Control.Exception.Lifted (IOException, catch)
import Control.Monad.Base (liftBase)
import Control.Monad.Error (MonadError(..), runErrorT)
import Control.Monad.Trans.Control (MonadBaseControl)
import Control.Monad.Trans.Resource (MonadResource, runResourceT)

import Data.Conduit
import Data.Conduit.List (consume)
import Data.Conduit.Text (decode, utf8)
import Data.Text (Text)

import Network.HTTP.Client
import Network.HTTP.Conduit (http)

main :: IO ()
main = do
result <- runErrorT $ runResourceT f
putStrLn $ "OK: " ++ show result

f :: (MonadBaseControl IO m, MonadResource m, MonadError String m) => m [Text]
f = do
req <- liftBase $ parseUrl "http://uri-that-does-not-exist.abc"
manager <- liftBase $ newManager defaultManagerSettings
response <- (http req manager `catch` \(e :: IOException) -> throwError $ show e)
response $$+- decode utf8 =$ consume

执行时,该程序以错误结束,输出如下:

InternalIOException getAddrInfo: does not exist (Name or service not known)

最佳答案

http 不会抛出 IOException,它会抛出 HttpExceptionInternalIOException 是后者的构造函数之一。

如果您想捕获所有异常,您应该捕获 HttpExceptionSomeException

关于exception - 在 MonadResource 实例中捕获 IO 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22547208/

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