用于读取带有错误处理的文件的 MonadResource

MonadResource for reading files with error handling

我正在创建一个将读取二进制文件的管道。事情可能会出错,所以我需要一个带有错误处理的 monad;现在 Maybe 已经足够了。

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

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

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

一个简单的方法是使用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!