Ich habe eine Funktion mit einem Typ Map Int String -> Proxy() a() Void IO b
. Gerade jetzt ist es await
s, tut was auch immer mit dem Wert, den es bekam, und ruft sich dann wieder auf. Ich möchte es ändern, um State (Map Int String)
zu verwenden, anstatt das als Argument übergeben zu haben, also kann ich einfach forever
verwenden und muss nicht jeden Zweig erinnern, um recurse zu haben. Ich bekomme, dass ich StateT
verwenden muss, um State
mit einer anderen Monade zu kombinieren, aber ich verstehe nicht, wo in dieser Art Unterschrift die StateT
gehört, oder ob ich oder lift
Funktionen wie get
muss. Was ist der richtige Typ für eine Funktion, die sowohl State (Map Int String)
als auch Proxy() a() Void IO b
ist?Wie funktioniert State mit Pipes?
6
A
Antwort
16
Hinweis: Proxy() a() Void = Consumer a
, so werde ich es für diese Antwort als Consumer
beziehen.
Die einfache Möglichkeit besteht darin, Ihre StateT
Monade-Transformer-Schicht außerhalb der Consumer
Schicht und dann sofort ausführen. Hier ein Beispiel:
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)
... und das ist, wie es in Aktion verhält:
>>> runEffect $ each ["Test", "ABC"] >-> example
Received value #0: "Test"
Received value #1: "ABC"
hoffe, das hilft! http://stackoverflow.com/questions/18471706/idiomatic-bidirectional-pipes-mit-downstream-state-without-loss – user3303858