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
                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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With