使用 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
。)
我正在探索使用 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
。)