haskellhaskell-pipes

pipes `take` with default value


I have a producer p with type Producer Message IO (Producer SB.ByteString IO ()). Now I need optionally skip some messages and optionally process certain number of messages:

       let p =
             (processMBFile f >->
              P.drop (optSkip opts)
              >->
              (case optLimit opts of
                 Nothing -> cat
                 Just n  -> ptake n)
             )
       in
         do
           restp <- runEffect $ for p processMessage

I could not use take from Pipes.Prelude because it returns () while I need to return an empty producer. The way I quickly haked it is by replacing take with my own implementation ptake:

emptyP :: Producer SB.ByteString IO ()
emptyP = return ()

ptake :: Monad m => Int -> Pipe a a m (Producer SB.ByteString IO ())
ptake = go
  where
    go 0 = return emptyP
    go n = do
        a <- await
        yield a
        go (n-1)

My question is: if there is a more elegant way to do this?


Solution

  • ptake differs from take only in the return value, so it can be implemented in terms of it using (<$):

    ptake n = emptyP <$ take n