简体   繁体   English

使用 State 的管道“运行”

[英]Pipes `run` with State

I have a producer:我有一个制片人:

p:: Producer Message IO r . p:: Producer Message IO r

I can process all messages using:我可以使用以下方法处理所有消息:

runEffect $ for p processMessage

where在哪里

processMessage:: Message -> Effect IO () . processMessage:: Message -> Effect IO ()

How can I implement stateful processing using something like:如何使用以下方法实现有状态处理:

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

Short answer:简短的回答:

  1. Modify your producer to be agnostic to the monad it's running in修改您的生产者以使其对其运行的 monad 不可知
  2. Your processMessage is fine你的processMessage很好
  3. The runEffect returns StateT MyState IO () , you need to evaluate it runEffect返回StateT MyState IO () ,你需要评估它

Longer answer with a dummy example:用一个虚拟例子来回答更长的问题:

Your producer is locked into the IO monad, you need to modify it to be either in MonadIO m or in the explicit state monad.您的生产者被锁定在IO monad 中,您需要将其修改为在MonadIO m或显式 state monad 中。

import Control.Monad.State
import Pipes

type Message = Int

p :: MonadIO m => Producer Message m ()
p = each [1..10]

The signature of your processMessage is already fine.您的processMessage的签名已经很好了。 I'm following your signature and adding some simple logic to exercise the IO and State functionality我正在遵循您的签名并添加一些简单的逻辑来练习 IO 和 State 功能

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

Then the final step.然后是最后一步。 runEffect:: Monad m => Effect m r -> m r , if you substitute the m with a concrete type, this ends up being runEffect:: Effect (StateT MyState IO) () -> StateT MyState IO () , meaning that you'll be left with the state monad which still needs to be executed. runEffect:: Monad m => Effect m r -> m r , if you substitute the m with a concrete type, this ends up being runEffect:: Effect (StateT MyState IO) () -> StateT MyState IO () , meaning that您将剩下 state monad 仍然需要执行。 There's three variants for executing the state monad, runStateT , evalStateT and execStateT .执行 state monad、 runStateTevalStateTexecStateT有三种变体。 I chose execStateT:: StateT MyState IO () -> IO MyState variant in this example, but choose whichever you need in your case.在本例中,我选择了execStateT:: StateT MyState IO () -> IO MyState变体,但在您的情况下选择您需要的任何一个。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM