¿Alguien puede caminar a través de esta función Haskell (estado relacionado mónada)?

StackOverflow https://stackoverflow.com/questions/1795785

  •  22-09-2019
  •  | 
  •  

Pregunta

tick :: State Int Int
tick = get >>= \n ->
       put (n+1) >>= \y ->
       return n

Estoy confundido en cuanto a cómo put (n+1) tiene ningún efecto sobre el resultado final de esta función en absoluto. Parece que esta función debe volver al estado inicial sin cambios. Estoy tratando de ejecutar este en mi mente, pero sigo quedando sin espacio para las cosas se mantienen en su lugar. : \

Si alguien pudiera caminar a través de la evaluación de esta función, sería de gran ayuda.

¿Fue útil?

Solución

  

... ¿Cómo se pone actualizando el estado en el primer lugar? Parece que acaba de estar sentado sin hacer nada ...

Ah, ahora entiendo su pregunta. Usted se pregunta cómo put (y get) de trabajo, ¿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 se ejecuta tick() dos veces, el estado se incrementará en dos ocasiones.

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

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. Es de esperar que se pondrá más claro cómo funciona Estado.

Otros consejos

Usted es completamente correcto. El "número" de "función" tick 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 Estado se 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, no estás viendo el cambio de estado. Sin embargo, si algún otro tipo de cálculo que sucede después de tick, se 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

que podría ayudar a escribir usando la notación do

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 influye en el resultado del cálculo, sí altera el estado en que se lleva a cabo dentro de la mónada estado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top