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!
Другие вопросы по тегам