Search code examples
haskellstate-monad

Use of put with >> in the state monad


From Thinking Functionally with Haskell (pg 248):

You can think of type State s a as being

type State s a = s -> (a,s) 

...

put :: s -> State s ()
get :: State s s
state :: (s -> (a,s)) -> State s a

... state can be defined using put and get:

state f = do {s <- get; let (a,s') = f s;
              put s'; return a}

Which I believe can be rewritten this way:

get >>= \s ->
    let (a,s') = fs in
        put s' >> return a

So what is the purpose of put s', if >> throws away its return value?


Solution

  • >> doesn't throw away everything from the first argument. The definition for the state monad (ignoring the newtype)

    a >> b = \s -> let (x, s') = a s in b s'
    

    So the state form the first argument is used by >>, but the 'return value' (the x component of the result) is ignored. That's the point of the state monad --- to track changes to the state without the programmer having to explicitly take them into account.

    Apparently, this isn't explained properly by what the OP has been reading, so here's how you can derive the definition above. The definition of >> across all monads is

    a >> b = a >>= \ _ -> b
    

    The definition of >>= for the state monad (ignoring newtypes) is

    a >>= f = \ s -> let (x, s') = a s in f x s'
    

    Now, substituting the definition of >>= into the definition of >> above and simplifying, we get:

    a >> b = let f = \ _ -> b in \ s -> let (x, s') = a s in f x s'
        = \ s -> let (x, s') = a s in (\ _ -> b) x s'
        = \ s -> let (x, s') = a s in b s'