Domanda

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

Sono confuso su come put (n+1) ha alcun effetto sul risultato finale di questa funzione a tutti. Sembra che questa funzione dovrebbe tornare allo stato iniziale invariato. Sto cercando di correre attraverso questo nella mia mente, ma io continuo a corto di spazio per tenere le cose a posto. : \

Se qualcuno mi poteva camminare attraverso la valutazione di questa funzione, sarebbe davvero utile.

È stato utile?

Soluzione

  

... Come è mette aggiornamento dello stato in primo luogo? Sembra essere appena seduto lì senza far nulla ...

Ah, ora ho capito la tua domanda. Vi state chiedendo come put (e get) funzionano, giusto?

Forse un esempio in JavaScript aiuterà (una lingua con stato mutevole reale):

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

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

Spero che questo dimostra che, mentre n non cambia, lo stato interno ancora viene aggiornata. Se si esegue tick() due volte, lo stato sarà incrementato due volte.

Per tornare a Haskell, ecco la definizione completa di (parti rilevanti) della monade 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)

Ora cercare di ampliare il vostro esempio tick ulteriormente inlining manualmente >>=, return, get e put. Speriamo che otterrà più chiaro come funziona Stato.

Altri suggerimenti

Hai perfettamente ragione. Il "risultato" di "funzione" tick è il valore iniziale dello stato.

Ora, naturalmente, tick non è la "funzione" reale, ma un calcolo in grado di leggere e scrivere Stato prima di produrre un risultato.
In questo caso, il Stato è aggiornato, ma si sta ancora restituendo il valore originale dello stato:

-- 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 questo caso, dal momento che non si è mai ispezionare di nuovo lo stato interno tick, non stai vedendo lo stato modificato. Tuttavia, se qualche altro calcolo avviene dopo tick, può vedere lo stato aggiornato.

Ad esempio, facendo tick due volte (la seconda leggerà lo stato aggiornato):

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

potrebbe aiutare a scrivere usando la notazione 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

mentre il put (n+1) non influisce il risultato del calcolo, si altera lo stato che si svolge all'interno monade stato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top