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