Kann jemand mich durch diese Haskell Funktion gehen (State Monade bezogen)?
Frage
tick :: State Int Int
tick = get >>= \n ->
put (n+1) >>= \y ->
return n
Ich bin verwirrt, wie put (n+1)
hat keine Auswirkungen auf das Endergebnis dieser Funktion überhaupt. Es scheint, wie diese Funktion sollte der Ausgangszustand unverändert zurück. Ich versuche, durch das in meinem Kopf zu laufen, aber ich immer laufen Platz heraus halten Dinge im Ort. : \
Wenn jemand mich durch die Auswertung dieser Funktion gehen könnte, wäre es sehr hilfreich sein.
Lösung
... Wie wird die Aktualisierung setzt den Zustand, in erster Linie? Es scheint nur zu nichts sitzen tun ...
Ah, jetzt verstehe ich Ihre Frage. Sie fragen sich, wie put
(und get
) Arbeit, nicht wahr?
Vielleicht ein Beispiel in JavaScript helfen (die Sprache mit dem tatsächlichen wandelbarem Zustand):
var s; // mutable state
function get() { return s; }
function put(x) { s = x; }
function tick() {
var n = get();
put(n + 1);
return n;
}
Ich hoffe, das das veranschaulicht, während n
nicht ändert, wird der innere Zustand wird noch aktualisiert. Wenn Sie tick()
zweimal ausführen, wird der Staat zweimal erhöht werden.
Um zu Haskell zurück, hier ist die vollständige Definition (die relevanten Teile) des State
Monade:
newtype State s a = State { runState :: s -> (a, s) }
instance Monad (State s) where
return a = State $ \s -> (a, s)
m >>= k = State $ \s -> let
(a, r) = runState m s
in runState (k a) r
get = State $ \s -> (s, s)
put s = State $ \_ -> ((), s)
Versuchen Sie nun tick
Beispiel noch weiter ausbauen, indem Sie manuell inlining >>=
, return
, get
und put
. Hoffentlich wird es mehr klar machen, wie Staat funktioniert.
Andere Tipps
Sie sind ganz richtig. Das „Ergebnis“ der tick
„Funktion“ ist der Anfangswert des Staates.
Jetzt ist natürlich tick
nicht die wirkliche „Funktion“, sondern eine Berechnung, die lesen und schreiben können Zustand bevor ein Ergebnis.
In diesem Fall wird der Zustand aktualisiert, aber Sie sind immer noch den ursprünglichen Wert des Staates zurückkehren:
-- 4 is the inital state
ghci> runState tick 4
(4, 5)
-- 4 is the result of the tick computation, 5 is the updated state
In diesem Fall, da Sie nie den Zustand wieder innerhalb tick
Inspektion, du bist nicht den geänderten Zustand zu sehen. Wenn jedoch eine andere Berechnung nach tick
geschieht, kann es den aktualisierten Zustand sehen.
Zum Beispiel tut tick
zweimal (der zweite wird den aktualisierten Zustand lesen):
-- 4 is the inital state
ghci> runState (tick >> tick) 4
(5, 6)
-- 5 is the result of the tick computation executed twice,
-- 6 is the updated state
es könnte helfen, es zu schreiben, mit do
Notation
tick :: State Int Int
tick = do
n <- get -- get the state
put (n+1) -- save an incremented state
return n -- return the original state
, während die put (n+1)
nicht das Ergebnis der Berechnung auswirken, hat es den Zustand ändern, die innerhalb des Staates Monade gehalten wird.