管道'运行'状态



我有一个制作人:

p :: Producer Message IO r.

我可以处理所有的消息使用:

runEffect $ for p processMessage

,

processMessage :: Message -> Effect IO ().

我如何实现有状态处理使用如下:

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

简短回答:

  1. 修改你的生产者,使其与它在
  2. 中运行的单子无关
  3. 你的processMessage很好
  4. runEffect返回StateT MyState IO (),你需要计算它

用一个假的例子回答更长的问题:

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

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 (),这意味着你将留下仍然需要执行的状态单子。执行状态单子有三种变体:runStateTevalStateTexecStateT。在这个例子中我选择了execStateT :: StateT MyState IO () -> IO MyState变体,但是根据您的情况选择您需要的。

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

最新更新