首页 文章

如何使用管道状态?

提问于
浏览
6

我有一个 Map Int String -> Proxy () a () Void IO b 类型的函数 . 现在它 await s,做任何有 Value 的东西,然后重新调用自己 . 我想将它更改为使用 State (Map Int String) 而不是将其作为参数传递,所以我可以使用 forever 并且不需要让每个分支都记得递归 . 我得到了我需要使用 StateTState 与另一个monad组合,但我不明白 StateT 属于该类型签名的位置,或者我是否需要 lift 函数如 get . State (Map Int String)Proxy () a () Void IO b 函数的正确类型是什么?

1 回答

  • 16

    注意: Proxy () a () Void = Consumer a ,所以我将这个答案称为 Consumer .

    简单的方法是将 StateT monad变换器层放在 Consumer 层之外,然后立即运行它 . 这是一个例子:

    import Control.Monad (forever)
    import Control.Monad.Trans.State.Strict
    import Pipes
    
    example :: (Show a) => Consumer a IO r
    example = flip evalStateT 0 $ forever $ do
        -- Inside here we are using `StateT Int (Consumer a IO) r`
        a <- lift await
        n <- get
        lift $ lift $ putStrLn $ "Received value #" ++ show n ++ ": " ++ show a
        put (n + 1)
    

    ......这就是它在行动中的表现:

    >>> runEffect $ each ["Test", "ABC"] >-> example
    Received value #0: "Test"
    Received value #1: "ABC"
    

相关问题