2014-02-13 69 views
6

我有一個Map Int String -> Proxy() a() Void IO b類型的函數。現在它await s,對它的價值做任何事情,然後重新調用它自己。我想將其更改爲使用State (Map Int String)而不是將其作爲參數傳遞,因此我可以使用forever,並且不需要讓每個分支都記住遞歸。我得到,我需要使用StateT結合State與另一個單子,但我不明白在那種類型簽名StateT所屬的位置,或者我是否需要lift功能,如get。功能的正確類型是State (Map Int String)Proxy() a() Void IO b如何使用狀態與管道?

+0

希望這有助於! http://stackoverflow.com/questions/18471706/idiomatic-bidirectional-pipes-with-downstream-state-without-loss – user3303858

回答

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"