我的目标是生成的最后一个值等于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在这个例子中,输入A没有累加...输入A上的yield x >-> accumulate确实做了我期望的事情,每次流都是一个新的流...
具有不同状态monad的管道顺序工作得很好,但在这里,我想以某种方式将它们嵌套在case模式中(类似于substream )……
发布于 2019-11-14 23:25:17
问题是,您过早地调用了evalStateP,丢弃了您希望在对accumulate的调用中保留的状态。尝试如下所示:
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请注意,Proxy有一个MonadState实例,因此如果使用mtl,则不需要手动提升状态操作。
https://stackoverflow.com/questions/58859184
复制相似问题