2009-11-25 4 views
7
tick :: State Int Int 
tick = get >>= \n -> 
     put (n+1) >>= \y -> 
     return n 

Ich bin verwirrt, wie put (n+1) irgendwelche Auswirkungen auf das Endergebnis dieser Funktion überhaupt hat. Es scheint, als ob diese Funktion den ursprünglichen Zustand unverändert zurückgeben sollte. Ich versuche, mir das durch den Kopf zu gehen, aber mir bleibt kein Platz mehr, um die Dinge in Position zu halten. : \Kann mir jemand durch diese Haskell-Funktion (Staatsmonat bezogen) gehen?

Wenn mir jemand durch die Auswertung dieser Funktion gehen könnte, wäre es wirklich hilfreich.

Antwort

10

... Wie puts aktualisiert den Zustand an erster Stelle? Es scheint einfach nur da zu sitzen und nichts zu tun ...

Ah, jetzt verstehe ich deine Frage. Sie fragen sich, wie put (und get) funktionieren, oder?

Vielleicht wird ein Beispiel in JavaScript helfen (die Sprache mit den tatsächlichen wandelbaren 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 zeigt, dass, während n nicht ändert, wird der innere Zustand wird noch aktualisiert. Wenn Sie zweimal tick() ausführen, wird der Status zweimal inkrementiert.

Um zurück zu Haskell zu bekommen, 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, indem manuell >>=, return, inlining get zu erweitern und put. Hoffentlich wird es klarer werden, wie State funktioniert.

+0

Ich habe dich um ganze 5 Sekunden geschlagen! Es ist komisch, wie ich dazu tendiere, Dinge selbst herauszufinden/nachdem ich die Frage gestellt habe. Ich schätze die Antworten! :) – Rayne

7

Sie haben völlig Recht. Das "Ergebnis" von tick "Funktion" ist der Anfangswert des Zustands.

Nun ist natürlich tick nicht die echte "Funktion", sondern eine Berechnung, die Zustand lesen und schreiben kann, bevor ein Ergebnis erzeugt wird.
In diesem Fall wird der Zustand aktualisiert wird, aber du bist immer noch den ursprünglichen Wert des Staates zurückkehrt:

-- 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 sind, da Sie nie den Zustand wieder innerhalb tick Inspizieren Sie Ich sehe den veränderten Zustand nicht. Wenn jedoch eine andere Berechnung nach tick erfolgt, kann der aktualisierte Status angezeigt werden.

Zum Beispiel tun tick zweimal (die 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 
+0

Was ich nicht verstehe ist, wie das passiert. Wie wird der Status aktualisiert, aber der Rückgabewert bleibt gleich?Wie stellt Puts den Staat überhaupt auf den neuesten Stand? Es scheint nur da zu sitzen und nichts zu tun. – Rayne

+0

Tatsächlich wird der Status aktualisiert, aber der Rückgabewert 'n' bleibt gleich. Siehe meine andere Antwort http://stackoverflow.com/questions/1795785/can-somebody-walk-me-through-this-haskell-function-state-monad-related/1796544#1796544 –

5

es helfen könnte es do Notation schreiben

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 Auswirkungen Das Ergebnis der Berechnung ändert den Zustand, der innerhalb der Zustandsmonade gehalten wird.

+0

Das hilft nicht wirklich. Ich habe mein Beispiel entziffert, damit ich versuchen konnte, es zu verstehen. Ich versuche herauszufinden, was hier unter der Oberfläche vor sich geht, um diesen Zustandswechsel herbeizuführen. – Rayne

+0

fair genug, ich hätte die Definitionen von get und put geschrieben, aber ich denke, das ist getan worden. – barkmadley

+0

Das hätte auch nicht geholfen. : p Ich hatte diese Definitionen schon so tief wie möglich angeschaut, es war dieses entscheidende Detail, das mir entging. Es ist nicht deine Schuld, es ist meine Schuld, dass ich eine Frage nicht richtig formulieren konnte. – Rayne

Verwandte Themen