Question

In Real World Haskell chapter, they give justification for (>>) like this:

We use this function when we want to perform actions in a certain order, but don't care what the result of one is.

They then give an nice example demonstrating it:

ghci > print "foo" >> print "bar"
"foo"
"bar"

Later on the chapter they use the same concept for generating random values in the State monad:

getRandom :: Random a => RandomState a
getRandom =
  get >>= \gen ->
  let (val, gen') = random gen in
  put gen' >>
  return val

But why in this case they are using the statement put gen' >> when ultimately they are ignoring it's output value. Why can't the above function be something like this:

getRandom :: Random a => RandomState a
getRandom =
  get >>= \gen ->
  let (val, gen') = random gen in
  return val

Just for completion of this question, I'm adding up the associated type definitions and functions for the above context:

newtype State s a = State {
  runState :: s -> (a, s)
  }

get :: State s s
get = State $ \s -> (s, s)

put :: s -> State s ()
put s = State $ \_ -> ((), s)

type RandomState a = State StdGen a
Was it helpful?

Solution

Because put has a side effect. It sticks something into the state monad that can be accessed and modified later.

It's return value is just () which is boring, so we don't care about it, but we certainly want to make sure we put the new random generator into the state.

Think of it like this, the state monad is really a function s -> (a, s). and put is

put s = \oldState -> (() , s)

So this has a side effect, it's throwing away the old state and replacing it. Consider this example

  test = put 1 >> get >>= \x -> put 2 >> get >>= \y -> return (x, y)

  -- or with do notation
  test' = do
    put 1
    x <- get
    put 2
    y <- get
    return (x, y)

Here x is 1 and y is 2. Clearly put has interesting effects beyond just it's return value.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top