Can someone get me through this Haskell feature (associated with the state monad)?

tick :: State Int Int tick = get >>= \n -> put (n+1) >>= \y -> return n 

I am confused about how put (n+1) has any effect on the final result of this function. It seems that this function should return to its original state unchanged. I'm trying to skip this in my mind, but I still don't have enough space to keep things in place.: \

If someone could go through evaluating this feature, that would be very helpful.

+7
haskell monads state
source share
3 answers

... How is a state update put in the first place? It seems just sitting there doing nothing ...

And now I understand your question. Are you curious how put (and get ) work?

Maybe an example in JavaScript will help (a language with actual mutable state):

 var s; // mutable state function get() { return s; } function put(x) { s = x; } function tick() { var n = get(); put(n + 1); return n; } 

Hopefully this illustrates that although n does not change, the internal state will still be updated. If you execute tick() twice, the state will increase twice.

To return to Haskell, here is the full definition of the (relevant parts) of the State monad:

 newtype State sa = State { runState :: s -> (a, s) } instance Monad (State s) where return a = State $ \s -> (a, s) m >>= k = State $ \s -> let (a, r) = runState ms in runState (ka) r get = State $ \s -> (s, s) put s = State $ \_ -> ((), s) 

Now try expanding your tick example again by manually entering >>= , return , get and put . I hope you will understand how the state works.

+10
source share

You are absolutely right. "The result of the" tick "function" is the initial state value.

Now, of course, tick not a real "function", but a computation that can read and write state until a result is obtained.
In this case, the state is updated, but you still return the original state value:

 -- 4 is the inital state ghci> runState tick 4 (4, 5) -- 4 is the result of the tick computation, 5 is the updated state 

In this case, since you no longer check the state inside the tick , you do not see the changed state. However, if some other calculations occur after tick , it may see an updated state.

For example, double tick (the second will read the updated state):

 -- 4 is the inital state ghci> runState (tick >> tick) 4 (5, 6) -- 5 is the result of the tick computation executed twice, -- 6 is the updated state 
+7
source share

this can help write it with do notation

 tick :: State Int Int tick = do n <- get -- get the state put (n+1) -- save an incremented state return n -- return the original state 

while put (n+1) does not affect the result of the calculation, it changes the state that is held in the state monad.

+5
source share

All Articles