Reputation: 443
runState (modify (+1) >> modify (+1)) 0
Can somebody explain how the above code produces ((),2)? Given (>>) :: Monad m => m a -> m b -> m b
I would have thought the first "modify (+1)" would be dropped resulting in ((),1).
Upvotes: 1
Views: 118
Reputation: 3790
You can thing about State s
monad as:
newtype State s a = State { runState :: s -> (a, s) }
And let's see how operator (>>) is implemented for this monad:
(State f) >> (State g) = State (g . snd . f)
And how modify work:
modify f = State $ \s -> ((), f s)
So compose all together:
modify (+1) >> modify (+1) => (State $ \s -> ((), s + 1)) >> ((State $ \s -> ((), s + 1)) => State (\s -> ((), (s + 1) + 1))
Then:
runState (State (\s -> ((), (s + 1) + 1))) 0 => (\s -> ((), (s + 1) + 1)) 0 => ((), (0 + 1) + 1) => ((), 2)
Upvotes: 2
Reputation: 43852
The >>
operator is not flip const
, even if it has a similar type signature. If you look at the default implementation, you can see it actually calls >>=
on its first argument:
a >> b = a >>= \_ -> b
For that reason, you can think of >>
as running a monadic action for its “side-effects” but discarding the result. If you inline the above definition of >>
in place of your example, the result you get becomes quite clear:
runState (modify (+1) >>= \_ -> modify (+1)) 0
This will obviously run modify (+1)
twice in the context of the state monad, so the resulting state will be 2
, not 1
.
Upvotes: 6