Search code examples
haskellhaskell-pipes

Haskell Pipes: How do I sort the output of a producer?


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.


Solution

  • 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.