haskell - Pipes (Haskell lib) - 具有不同状态单子的管道管道
问题描述
我的目标是使最后产生的值等于 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
在这个例子中, Input A
s 没有累积......yield x >-> accumulate
在 Input A 上确实做了我所期望的,流每次都是一个新的......
按顺序使用不同状态单子的管道管道效果很好,但在这里我想以某种方式将它们嵌套在案例模式中(就像子流一样)......
解决方案
问题是你调用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
.
推荐阅读
- android - 使用毕加索将base64字符串加载到imageview中
- ruby - 如何使用.include?捕获导致相同操作的多个选项
- php - 如何对“私有”构造函数进行例外处理?
- java - 如何在 Java 8 的范围内生成具有指定大小的随机整数的列表?
- c# - Unity3D 引擎类中不应该出现一致的“CS0201”错误
- regex - 如何计算最后出现在单元格中的Google表格单元格中特定字符的出现次数作为标准?
- java - 不兼容的类型。必需:T,找到 T。为什么?
- excel - 如何让 Excel 用户表单验证然后编辑用户表单
- java - SpringBootTest 和 MockMvc 创建了大量控制台日志记录 - 如何禁用?
- javascript - 异步命名箭头函数错误“意外令牌”