【问题标题】:Pipes (Haskell lib) - piping pipes with different state monadPipes (Haskell lib) - 具有不同状态单子的管道管道
【发布时间】:2019-11-14 14:32:15
【问题描述】:

我的目标是使最后产生的值等于 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

在此示例中,输入 As 不会累积...输入 A 上的yield x &gt;-&gt; accumulate 确实符合我的预期,每次流都是一个新流...

具有不同状态 monad 的管道按顺序运行效果很好,但在这里我想以某种方式将它们嵌套在 case 模式中(就像子流一样)......

【问题讨论】:

    标签: haskell haskell-pipes


    【解决方案1】:

    问题是您过早地调用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,则无需手动解除状态操作。

    【讨论】:

    • 是的,我实际上需要pipeline :: Pipe Input Integer (StateT AnotherState IO) () 的解决方案...
    猜你喜欢
    • 2016-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-28
    • 1970-01-01
    • 2015-06-01
    • 1970-01-01
    相关资源
    最近更新 更多