Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing an accumulating function using Conduit

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?

like image 374
Christophe Avatar asked Feb 15 '26 22:02

Christophe


1 Answers

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

like image 76
duplode Avatar answered Feb 17 '26 21:02

duplode



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!