1

I have the following piece of code:

import Control.Monad (unless)
import Pipes
import qualified Pipes.Prelude as P
import System.FilePath.Posix ((</>))
import System.Posix.Directory (DirStream, openDirStream, readDirStream)

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
  ds <- lift $ openDirStream top
  produceFiles ds

runTest top = runEffect $ getDC top >-> P.map (top</>) >-> P.stdoutLn

It prints all the files in the directory top. How do I sort the output before I print it? Do I need to write a consumer that "drains" the output first into a list and then sorts it? I'm using pipes-4.1.4.

Jan Synáček
  • 355
  • 2
  • 9

2 Answers2

4

toListM from Pipes.Prelude converts a producer into a list. We can use that and proceed without pipes afterwards:

runTest top = do
  ds <- P.toListM (getDC top >-> P.map (top</>))
  mapM_ print $ sort ds

Or a bit more pipe-like using usual monadic operators:

runTest top = P.toListM (getDC top >-> P.map (top</>)) >>= mapM_ print . sort

Grabbing all the Producer contents brings us outside streaming abstraction, which is why toListM returns a plain list instead of being a pipe.

András Kovács
  • 29,931
  • 3
  • 53
  • 99
1

Yes, you need to drain the output first, either into a list our some other structure. Sorting is inherently non-streaming because it may be, for instance, that the last element coming in should be the first going out.

dfeuer
  • 48,079
  • 5
  • 63
  • 167