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