...How is puts updating the state in the first place? It seems to just be sitting there doing nothing...
Ah, now I understand your question. You're wondering how put
(and get
) work, right?
Maybe an example in JavaScript will help (a language with actual mutable state):
var s; // mutable state
function get() { return s; }
function put(x) { s = x; }
function tick() {
var n = get();
put(n + 1);
return n;
}
I hope this illustrates that, while n
doesn't change, the internal state still will get updated. If you execute tick()
twice, the state will be incremented twice.
To get back to Haskell, here's the full definition of (the relevant parts) of the State
monad:
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)
Now try to expand your tick
example even further by manually inlining >>=
, return
, get
and put
. Hopefully it will get more clear how State works.