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

Estoy confundido en cuanto a cómo put (n+1) tiene algún efecto en el resultado final de esta función. Parece que esta función debería devolver el estado inicial sin cambios. Intento pasar por esto en mi mente, pero me quedo sin espacio para mantener las cosas en su lugar. : \¿Puede alguien guiarme a través de esta función de Haskell (relacionada con la mónada de estado)?

Si alguien me guiara en la evaluación de esta función, sería realmente útil.

Respuesta

10

... ¿Cómo se pone la actualización del estado en primer lugar? Parece estar sentado allí sin hacer nada ...

Ah, ahora entiendo su pregunta. ¿Te estás preguntando cómo funcionan put (y get), ¿verdad?

Tal vez un ejemplo en JavaScript ayudará (un lenguaje con el estado mutable real):

var s; // mutable state 
function get() { return s; } 
function put(x) { s = x; } 

function tick() { 
    var n = get(); 
    put(n + 1); 
    return n; 
} 

espero que esto ilustra que, mientras n no cambia, el estado interno todavía se actualizará. Si ejecuta tick() dos veces, el estado se incrementará dos veces.

para volver a Haskell, aquí está la definición completa de (las partes pertinentes) de la State mónada:

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) 

Ahora trata de ampliar su ejemplo tick aún más mediante la inclusión entre líneas manualmente >>=, return, get y put. Con suerte, se verá más claro cómo funciona el estado.

+0

¡Te gané por 5 segundos enteros! Es extraño cómo tiendo a resolver las cosas por mi cuenta/después/He hecho la pregunta. Aprecio las respuestas! :) – Rayne

7

Tiene toda la razón. El "resultado" de tick "función" es el valor inicial del estado.

Ahora, por supuesto, tick no es la "función" real, sino un cálculo que puede leer y escribir estado antes de producir un resultado.
En este caso, el estadose actualiza, pero todavía se está volviendo el valor original del estado:

-- 4 is the inital state 
ghci> runState tick 4 
(4, 5) 
-- 4 is the result of the tick computation, 5 is the updated state 

En este caso, ya que nunca se está inspeccionando el estado de nuevo en el interior tick, se No estoy viendo el cambio de estado. Sin embargo, si ocurre algún otro cálculo después de tick, puede ver el estado actualizado.

Por ejemplo, haciendo tick dos veces (la segunda leerá el estado actualizado):

-- 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

Lo que no entiendo es cómo está sucediendo esto. ¿Cómo se actualiza el estado, pero el valor de retorno sigue siendo el mismo?¿Cómo se pone la actualización del estado en primer lugar? Parece estar sentado allí sin hacer nada. – Rayne

+0

De hecho, el estado se está actualizando, pero el valor de retorno, 'n' se mantiene igual. Ver mi otra respuesta http://stackoverflow.com/questions/1795785/can-somebody-walk-me-through-this-haskell-function-state-monad-related/1796544#1796544 –

5

que podría ayudar a escribirlo usando do notación

tick :: State Int Int 
tick = do 
    n <- get -- get the state 
    put (n+1) -- save an incremented state 
    return n -- return the original state 

mientras que el put (n+1) no tiene impacto el resultado del cálculo, altera el estado que se mantiene dentro de la mónada de estado.

+0

Eso realmente no ayuda. Desané mi ejemplo para poder tratar de entenderlo. Estoy tratando de descubrir qué está pasando debajo de la superficie para hacer que este cambio de estado ocurra. – Rayne

+0

lo suficientemente justo, habría publicado las definiciones de get y put, pero supongo que eso ya está hecho. – barkmadley

+0

Eso tampoco habría ayudado. : p Ya había mirado esas definiciones lo más profundamente posible, era ese detalle crucial que escapaba a mi vista. No es tu culpa, es mi culpa por no poder formular una pregunta correctamente. – Rayne

Cuestiones relacionadas