[英]Pipes (Haskell lib) - piping pipes with different state monad
My goal is to have the last value produced equal to 80 (40 + 40) (see code below)...我的目标是使最后产生的值等于 80 (40 + 40)(参见下面的代码)...
import Pipes
import Pipes.Prelude
import Pipes.Lift
import Control.Monad.State.Strict
data Input = A Integer | B Integer | C Integer
main :: IO ()
main = runEffect $ each [A 10,B 2,C 3,A 40,A 40] >-> pipeline >-> print
pipeline :: Pipe Input Integer IO ()
pipeline = for cat $ \case
A x -> yield x >-> accumulate
B x -> yield x
C x -> yield x
accumulate :: Pipe Integer Integer IO ()
accumulate = evalStateP 0 accumulate'
accumulate' :: Pipe Integer Integer (StateT Integer IO) ()
accumulate' = go
where
go = do
x <- await
lift $ modify (+x)
r <- lift get
yield r
go
With this example Input A
s are not accumulated... yield x >-> accumulate
on Input A does do what I'm expected, the stream is a new one each time...在此示例中,输入
A
没有累积... yield x >-> accumulate
确实符合我的预期,stream 每次都是新的...
Piping pipes with different state monad sequentially works well but here somehow I want to nest them in the case pattern (like a substream somehow)...具有不同 state monad 的管道管道顺序运行良好,但在这里我想以某种方式将它们嵌套在案例模式中(就像子流一样)......
The problem is that you call evalStateP
too early, discarding state you want to preserve across calls to accumulate
.问题是您过早地调用
evalStateP
,丢弃了 state 您想要在调用中保留的accumulate
。 Try something like this:尝试这样的事情:
pipeline :: Pipe Input Integer IO ()
pipeline = evalStateP 0 $ for cat $ \case
A x -> yield x >-> accumulate
B x -> yield x
C x -> yield x
accumulate :: Pipe Integer Integer (StateT Integer IO) ()
accumulate = for cat $ \x -> do
modify (+x)
r <- get
yield r
Note that Proxy
has a MonadState
instance, so you don't need to lift state operations manually if you use mtl
.请注意,
Proxy
有一个MonadState
实例,因此如果您使用mtl
,则无需手动解除 state 操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.