Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何捕获runResourceT中的异常_Haskell - Fatal编程技术网

Haskell 如何捕获runResourceT中的异常

Haskell 如何捕获runResourceT中的异常,haskell,Haskell,我希望在不释放资源的情况下捕获runResourceT内部的异常,但是函数catch在IO内部运行计算。有没有一种方法可以捕获runResourceT内部的异常,或者什么是重构代码的推荐方法 谢谢你的帮助 {-# LANGUAGE FlexibleContexts #-} module Main where import Control.Exception as EX import Control.Monad.IO.Class import Control.Monad.Trans.Resou

我希望在不释放资源的情况下捕获runResourceT内部的异常,但是函数catch在IO内部运行计算。有没有一种方法可以捕获runResourceT内部的异常,或者什么是重构代码的推荐方法

谢谢你的帮助

{-# LANGUAGE FlexibleContexts #-}

module Main where

import Control.Exception as EX
import Control.Monad.IO.Class
import Control.Monad.Trans.Resource

type Resource = String

allocResource :: IO Resource
allocResource = let r = "Resource"
                    in putStrLn (r ++ " opened.") >> return r

closeResource :: Resource -> IO ()
closeResource r = putStrLn $ r ++ " closed."

withResource :: ( MonadIO m
                , MonadBaseControl IO m
                , MonadThrow m
                , MonadUnsafeIO m
                ) => (Resource -> ResourceT m a) -> m a 
withResource f = runResourceT $ do
    (_, r) <- allocate allocResource closeResource
    f r

useResource :: ( MonadIO m
               , MonadBaseControl IO m
               , MonadThrow m
               , MonadUnsafeIO m
               ) => Resource -> ResourceT m Int
useResource r = liftIO $ putStrLn ("Using " ++ r) >> return 1

main :: IO ()
main = do
  putStrLn "Start..."

  withResource $ \r -> do

    x <- useResource r

    {-- This does not compile as the catch computation runs inside IO
    y <- liftIO $ EX.catch (useResource r)
                           (\e -> do putStrLn $ show (e::SomeException)
                                     return 0)
    --} 

    return ()

  putStrLn "Done."
{-#语言灵活上下文}
模块主要在哪里
导入控制。异常为EX
导入控制.Monad.IO.Class
导入控制.Monad.Trans.Resource
类型资源=字符串
allocResource::IO资源
allocResource=let r=“资源”
在putStrLn中(r++“打开”)>>返回r
closeResource::Resource->IO()
closeResource r=putStrLn$r++“已关闭。”
withResource::(MonadIO m
,MonadBaseControl IO m
,MonadThrow m
,MonadUnsafeIO m
)=>(资源->资源并购)->并购
withResource f=runResourceT$do
(ur)资源->资源m Int
useResource r=liftIO$putStrLn(“使用”++r)>>返回1
main::IO()
main=do
putStrLn“开始…”
withResource$\r->do

x
ResourceT
是来自该软件包的一个实例,该软件包设计用于将控制结构(如
forkIO
catch
提升为转换单体)

该软件包构建在monad控件之上,包含具有标准控件结构版本的模块,可在任何
MonadBaseControl
中工作。对于异常处理,您可以使用模块中的函数。因此,只需将
import qualified Control.Exception.Lifted改为EX
1,您的代码就可以正常工作了


1注意此处的
合格
;相当令人困惑的是,
import A as B
实际上将
A
中的所有定义导入范围,并将
B
定义为模块的别名!您需要使用
qualified
来确保定义不被纳入范围,而是通过
B
别名专门访问。

作为替代方法,您可以使用包中的实例。您只需从
Control.Monad.catch
替换广义版本的
catch

import Control.Monad.Catch
…
main = do
  …
  withResource $ \r -> do
    …
    y <- Control.Monad.Catch.catch (useResource r) (\e -> …)
import Control.Monad.Catch
…
main=do
…
withResource$\r->do
…
y…)

感谢您的回答和评论。它的工作原理和预期一样,帮助我更好地理解monads变形金刚。