Inizialmente avrei postato questo post come commento, ma ho deciso di esporre un po 'di più.
In senso stretto, get
non "accetta" un argomento. Penso che molto di ciò che sta accadendo sia mascherato da ciò che non vedi, le definizioni di istanza della monade di Stato.
get
è in realtà un metodo della classe MonadState. La monade Stato è un'istanza di MonadState, fornendo la seguente definizione di get
:
get = State $ \s -> (s,s)
In altre parole, get
solo restituisce una monade Stato molto di base (ricordando che una monade può essere pensato come un "wrapper" per un calcolo), in cui qualsiasi input s
nel calcolo restituirà una coppia di s
come risultato.
La prossima cosa che dobbiamo guardare è >>=
, quale Stato definisce nel seguente modo:
m >>= k = State $ \s -> let
(a, s') = runState m s
in runState (k a) s'
Quindi, >>=
sta per produrre un nuovo calcolo, che non sarà calcolato fino a quando non ottiene uno stato iniziale (questo è vero per tutti i calcoli statali quando sono nella loro forma "incartata"). Il risultato di questo nuovo calcolo si ottiene applicando ciò che si trova sul lato destro dello >>=
al risultato dell'esecuzione del calcolo che era sul lato sinistro.(Che è una frase piuttosto confusa che può richiedere un ulteriore lettura o due.)
ho trovato molto utile per "desugar" tutto ciò che sta succedendo. Ciò richiede molto più digitazione, ma dovrebbe rendere molto chiara la risposta alla tua domanda (da cui il get
arriva). Si noti che la segue deve essere considerato psuedocodarlo ...
test x =
State $ \s -> let
(a,s') = runState (State (\s -> (s,s))) s --substituting above defn. of 'get'
in runState (rightSide a) s'
where
rightSide test =
let test' = x ++ test in
State $ \s2 -> let
(a2, s2') = runState (State $ \_ -> ((), test')) s2 -- defn. of 'put'
in runState (rightSide2 a2) s2'
rightSide2 _ =
-- etc...
Questo dovrebbe rendere evidente che il risultato finale della nostra funzione è un nuovo calcolo Stato che avrà bisogno di un valore iniziale (s
) per rendere il resto del succedono cose Hai fornito s
come "testtest"
con la tua chiamata runState
. Se si sostituisce "testtest" per s
nel pseudocodice sopra, vedrete che la prima cosa che succede è corriamo get
con "testtest", come il 'stato iniziale'. Questo produce ("testtest", "testtest")
e così via.
Ecco dove get
ottiene il vostro stato iniziale "testtest". Spero che questo ti aiuti!
Non riuscivo a pensare a una parola migliore quando ho detto che "prendeva" una discussione. Grazie per questa spiegazione molto dettagliata. – Rayne