A good first step would be to have a version of withFile
which opened several files at the same time and let you work with the list of Handle
s in a callback (while still offering the cleanup assurances of withFile
).
We can build such a function using ContT
:
import Control.Monad.Trans.Cont
import System.IO
withManyFiles :: [FilePath] -> IOMode -> ([Handle] -> IO r) -> IO r
withManyFiles files mode =
runContT $ traverse (`withFileCont` mode) files
where
withFileCont :: FilePath -> IOMode -> ContT r IO Handle
withFileCont filepath mode = ContT (withFile filepath mode)
This function that filters the list of Handle
s and keeps only those that haven’t reached eof could also be useful:
filterEOF :: [Handle] -> IO [Handle]
filterEOF = filterM $ \h -> do
eof <- hIsEOF h
-- hClose will get called again at the end of withManyFiles,
-- but that isn't a problem
when eof $ hClose h
return (not eof)