6

我有一个 type 的函数Map Int String -> Proxy () a () Void IO b。现在它await是,用它得到的值做任何事情,然后重新调用它自己。我想将其更改为使用State (Map Int String),而不是将其作为参数传递,因此我可以只使用forever并且不需要让每个分支都记住递归。我知道我需要用来与另一个 monadStateT结合State,但我不明白该类型签名的StateT所属位置,或者我是否需要liftget. 既是 aState (Map Int String)又是 a 的函数的正确类型是Proxy () a () Void IO b什么?

4

1 回答 1

16

注意:Proxy () a () Void = Consumer a,所以我将其称为Consumer此答案。

简单的方法是将您的StateTmonad 转换器层放在该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"
于 2014-02-13T02:15:58.067 回答