MonadResource для чтения файлов с обработкой ошибок
Я создаю Conduit, который будет читать двоичные файлы. Материал может пойти не так, поэтому мне нужна монада с некоторой обработкой ошибок; теперь Maybe
достаточно хорош
Я хотел бы использовать sourceFile
, что требует, чтобы монада канала была MonadResource
и в этом суть проблемы.
Я вижу из документов, что, например, MaybeT m
есть экземпляр, но это требует m
уже быть MonadResource
; на самом деле это верно для всех случаев. С моим ограниченным пониманием это звучит как курица с яйцом, требуя, чтобы я написал MonadResource
экземпляр от руки не смотря ни на что?
Я предполагаю, что для чтения файлов моя монада должна содержать IO. Так значит ли это, что я должен написать MonadResource
экземпляр для MaybeT IO
? Если да, какие-нибудь указатели о том, как это сделать?
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!