Search code examples
haskellconduit

Keep every nth element of a conduit stream


I'm using Conduit to parse some data in a stream-like manner. At some point in the stream I require every 12th element. Is there a convenient way to do this?

I'm currently explicitly waiting for 12 elements just to return the first element:

get12th :: Monad m => Conduit Int m Int
get12th = loop
  where
    loop = do
        v1 <- await
        _ <- await
        _ <- await
        _ <- await
        _ <- await
        _ <- await
        _ <- await
        _ <- await
        _ <- await
        _ <- await
        _ <- await
        _ <- await
        case v1 of
            Nothing -> return ()
            Just x -> do
              yield x >> loop

It does work, but I'm wondering if this is the best way to do it.


Solution

  • Thanks to Alec, Chad Gilbert and Michael Snoyman, I've come to the following solution:

    get12th :: Monad m => Conduit Int m Int
    get12th = loop
      where loop = do
              v <- await
              case v of
                Just x  -> yield x >> CL.drop 11 >> loop
                Nothing -> return ()
    

    This solution uses the drop function to get rid of the duplicate awaits. It yields the first value as soon as it receives it, before waiting for the other values.