I am exploring the possibility to use the Conduit package in order to implement complex event processing in Haskell. As an example, I would like to implement an accumulating function using Conduit.
Starting from:
#!/usr/bin/env stack
-- stack script --resolver lts-8.12 --package conduit-combinators
{-# LANGUAGE ExtendedDefaultRules #-}
import Conduit
trans :: Monad m => ConduitM Int Int m ()
trans = do
mapC (* 2)
main :: IO ()
main = runConduit $ yieldMany [1..10] .| trans .| mapM_C print
I get:
2 4 6 8 10 12 14 16 18 20
How can I modify trans
so that it yields
1 3 6 10 15 21 28 36 45 55
instead?
scanlC
, which is an "analog of scanl
for lists", does almost what you want. I say "almost" because scanlC
asks for and yields an initial "seed" value, which you don't need nor want (cf. the difference between scanl
and scanl1
). That being so, you will need to explicitly feed the first streamed value as the seed:
trans :: Monad m => ConduitM Int Int m ()
trans = await >>= maybe (return ()) (scanlC (+))
(The -- clearly inferior -- alternative would be having trans = scanlC (+) 0
and using dropC 1
in the next step of the pipeline to get rid of the 0
.)