使用 Conduit 实现累积功能

Implementing an accumulating function using Conduit

我正在探索使用 Conduit 包以在 Haskell 中实现复杂事件处理的可能性。例如,我想使用 Conduit 实现一个累加函数。

开始于:

#!/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

我得到:

2 4 6 8 10 12 14 16 18 20

我如何修改 trans 使其产生

1 3 6 10 15 21 28 36 45 55

代替?

scanlC,这是一个 "analog of scanl for lists",几乎可以满足您的需求。我说 "almost" 是因为 scanlC 要求并产生一个初始的 "seed" 值,你不需要也不想要它(参见 scanl 和 [=15= 之间的区别) ]).既然如此,您将需要明确地将第一个流值作为种子提供:

trans :: Monad m => ConduitM Int Int m ()
trans = await >>= maybe (return ()) (scanlC (+))

(显然较差的替代方案是使用 trans = scanlC (+) 0 并在管道的下一步中使用 dropC 1 来摆脱 0。)