我有一个Map Int String -> Proxy () a () Void IO b
类型的函数。现在它await
s,做任何有价值的东西,然后重新调用自己。我想将其更改为使用State (Map Int String)
而不是将其作为参数传递,因此我可以使用forever
并且不需要让每个分支都记得递归。我知道我需要使用StateT
将State
与另一个monad合并,但我不明白StateT
属于该类型签名的位置,或者我是否需要{ {1}} lift
等功能。对于get
和State (Map Int String)
?
答案 0 :(得分: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"