【问题标题】:Pipes `run` with State带有状态的管道`run`
【发布时间】:2021-02-17 00:14:44
【问题描述】:

我有一个制作人:

p :: Producer Message IO r.

我可以使用以下方法处理所有消息:

runEffect $ for p processMessage

在哪里

processMessage :: Message -> Effect IO ().

我怎样才能使用类似的东西来实现有状态处理:

processMessage :: Message -> Effect (StateT MyState IO) ()?

【问题讨论】:

    标签: haskell haskell-pipes


    【解决方案1】:

    简答:

    1. 修改您的生产者,使其对其运行的 monad 不可知
    2. 你的processMessage 很好
    3. runEffect 返回StateT MyState IO (),你需要评估它

    更长的答案,一个虚拟的例子:

    您的生产者被锁定在 IO monad 中,您需要将其修改为处于 MonadIO m 或显式状态 monad。

    import Control.Monad.State
    import Pipes
    
    type Message = Int
    
    p :: MonadIO m => Producer Message m ()
    p = each [1..10]
    

    您的processMessage 的签名已经可以了。我正在遵循您的签名并添加一些简单的逻辑来执行 IO 和 State 功能

    processMessage :: Message -> Effect (StateT MyState IO) ()
    processMessage msg = do
      modify (+ msg)
      liftIO (print msg)
    

    然后是最后一步。 runEffect :: Monad m => Effect m r -> m r,如果你将m 替换为一个具体的类型,这最终会是runEffect :: Effect (StateT MyState IO) () -> StateT MyState IO (),这意味着你将留下仍然需要执行的状态单子。执行状态 monad 有三个变体,runStateTevalStateTexecStateT。在此示例中,我选择了 execStateT :: StateT MyState IO () -> IO MyState 变体,但请选择您需要的任何一个。

    main :: IO ()
    main = do
      st <- execStateT (runEffect $ for p processMessage) 0
      putStrLn $ "End state: " <> show st
    

    【讨论】:

      猜你喜欢
      • 2016-09-26
      • 2021-11-08
      • 1970-01-01
      • 1970-01-01
      • 2019-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多