2017-10-28 76 views
0

我正在创建一个将读取二进制文件的Conduit。东西可能会出错,所以我需要一个monad来处理一些错误;现在Maybe已经足够了。MonadResource用于读取具有错误处理的文件

我想使用sourceFile,它要求管道monad是MonadResource,这是问题的关键。

我从the docs看到,例如, MaybeT m有一个实例,但它需要m已经是MonadResource;事实上,所有情况都是如此。由于我的理解有限,这听起来像鸡与鸡蛋,要求我无论如何都手写一个MonadResource实例?

我认为要读取文件,我的monad必须包含IO。那么这是否意味着我必须为MaybeT IO写一个MonadResource实例?如果是这样,任何关于如何做到这一点的指针?

+1

'(MonadThrow米,MonadBase IO米,MonadIO米,应用型米)=> MonadResource( ResourceT m)'不是递归的。 – melpomene

+0

啊哈,错过了。时间潜入并学习'ResourceT'如何工作我猜.. – jorgen

+0

只是某种形式的'main = runResourceT。 runConduit $ sourceFile ...应该可以工作。 –

回答

1

一个简单的方法是使用tryC例如:

module Main (main) where 

import   Conduit 
import   Control.Exception (SomeException) 
import qualified Control.Monad.Trans.Resource as R 
import   Data.Monoid ((<>)) 
import   System.Environment (getArgs) 

main :: IO() 
main = do 
    [fname] <- getArgs 
    r <- R.runResourceT . runConduit . tryC $ sourceFile fname .| await >>= pure 
    case r of 
    Left e -> putStrLn $ "Failed to read file content with " <> show (e :: SomeException) 
    Right r' -> putStrLn $ "File content: " <> show r' 

然后你得到:

[nix-shell:/tmp]$ ghc -Wall M.hs && ./M /tmp/doesnt_exist 
[1 of 1] Compiling Main    (M.hs, M.o) 
Linking M ... 
Failed to read file content with /tmp/doesnt_exist: openBinaryFile: does not exist (No such file or directory) 

[nix-shell:/tmp]$ ghc -Wall M.hs && ./M /tmp/hello-file 
File content: Just "Hello world!