1

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?

krokodil
  • 1,326
  • 10
  • 18
  • 1
    If I'm not overlooking anything, since you are always returning `emptyP`, your `ptake` can be written as `ptake n = emptyP <$ take n` – duplode Feb 14 '21 at 12:07
  • I am also surprised there is no generic version of `emptyP` in the library. – krokodil Feb 14 '21 at 16:47

1 Answers1

0

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

ptake n = emptyP <$ take n
duplode
  • 33,731
  • 7
  • 79
  • 150