2017-10-28 52 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!