user1897830
user1897830

Reputation: 443

Haskell (>>) operator

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

Answers (2)

freestyle
freestyle

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

Alexis King
Alexis King

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

Related Questions