管道 `运行` 与状态
Pipes `run` with State
我有制作人:
p :: Producer Message IO r
.
我可以使用以下方法处理所有消息:
runEffect $ for p processMessage
哪里
processMessage :: Message -> Effect IO ()
.
我如何使用类似的东西实现状态处理:
processMessage :: Message -> Effect (StateT MyState IO) ()
?
简答:
- 修改您的生产者,使其与 运行 在
中的 monad 无关
- 你的
processMessage
很好
runEffect
returnsStateT 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 和状态功能
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。执行状态 monad 有三种变体,runStateT
、evalStateT
和 execStateT
。我在此示例中选择了 execStateT :: StateT MyState IO () -> IO MyState
变体,但请根据您的情况选择所需的变体。
main :: IO ()
main = do
st <- execStateT (runEffect $ for p processMessage) 0
putStrLn $ "End state: " <> show st
我有制作人:
p :: Producer Message IO r
.
我可以使用以下方法处理所有消息:
runEffect $ for p processMessage
哪里
processMessage :: Message -> Effect IO ()
.
我如何使用类似的东西实现状态处理:
processMessage :: Message -> Effect (StateT MyState IO) ()
?
简答:
- 修改您的生产者,使其与 运行 在 中的 monad 无关
- 你的
processMessage
很好 runEffect
returnsStateT 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 和状态功能
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。执行状态 monad 有三种变体,runStateT
、evalStateT
和 execStateT
。我在此示例中选择了 execStateT :: StateT MyState IO () -> IO MyState
变体,但请根据您的情况选择所需的变体。
main :: IO ()
main = do
st <- execStateT (runEffect $ for p processMessage) 0
putStrLn $ "End state: " <> show st