1

I'm using haskell-pipes to recursively traverse a directory and print the files. How do I handle exceptions from the Producer, which is a monad transformer? bracket and handle do not work in this case.

import Control.Exception (handle, SomeException(..))
import Control.Monad (unless)
import System.FilePath.Posix ((</>))
import Pipes
import qualified Pipes.Prelude as P
import System.Posix.Directory (DirStream, openDirStream, closeDirStream, readDirStream)
import System.Posix.Files (getFileStatus, isDirectory)

produceFiles :: DirStream -> Producer FilePath IO ()
produceFiles ds = do
  path <- lift $ readDirStream ds
  yield path
  unless (path == "") $ produceFiles ds

getDC :: FilePath -> Producer FilePath IO ()
getDC top = do
  {-
    lift $ handle (\(SomeException e) -> putStrLn (show e)) $ do
    ds <- openDirStream top
    -- DOESN'T WORK: produceFiles ds
    -- I would have to "delift" the above somehow.
    closeDirStream ds
  -}
  ds <- lift $ openDirStream top
  produceFiles ds
  lift $ closeDirStream ds

getDC' :: FilePath -> Producer FilePath IO ()
getDC' top = getDC top >-> P.filter (`notElem` [".", ".."]) >-> P.map (top</>)

getDCR :: FilePath -> Producer FilePath IO ()
getDCR top = for (getDC' top) $ \f -> do
  st <- lift $ getFileStatus f
  if isDirectory st && f /= top
  then getDCR f
  else yield f

test top = runEffect $ for (getDCR top) (lift . putStrLn)

main = test "/usr/share"
Jan Synáček
  • 355
  • 2
  • 9

1 Answers1

3

You can import bracket, handle and other exception handling facilities from Pipes.Safe.

András Kovács
  • 29,931
  • 3
  • 53
  • 99
  • Thanks! I just realized pipes-safe was mentioned in the conclusion section of the pipes tutorial. It's quite hidden there... – Jan Synáček Mar 29 '16 at 12:18