views:

255

answers:

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

I'm confused as to how put (n+1) has any effect on the end result of this function at all. It seems like this function should return the initial state unchanged. I'm trying to run through this in my mind, but I keep running out of room to hold things in place. :\

If someone could walk me through the evaluation of this function, it would be really helpful.

+7  A: 

You're completely right. The "result" of tick "function" is the initial value of the state.

Now of course, tick isn't the real "function", but a computation that can read and write state before producing a result.
In this case, the state is updated, but you're still returning the original value of the state:

-- 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're never inspecting the state again inside tick, you're not seeing the changed state. However, if some other computation happens after tick, it can see the updated state.

For example, doing tick twice (the second one 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
Tom Lokhorst
What I don't understand is how this is happening. How is the state getting updated, but the return value staying the same? How is puts updating the state in the first place? It seems to just be sitting there doing nothing.
Rayne
I took me several hours, but it's finally clicked. I see now that the value put is returning is never used, so the result value is the initial result which is the initial state, but the state is changed. What a mindfuck. :|
Rayne
Indeed, the state is being updated, but the return value, `n` stays the same. See my other answer http://stackoverflow.com/questions/1795785/can-somebody-walk-me-through-this-haskell-function-state-monad-related/1796544#1796544
Tom Lokhorst
+5  A: 

it might help to write it using 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 the put (n+1) does not impact the result of the computation, it does alter the state that is held within the state monad.

barkmadley
That doesn't really help. I desugared my example so I could try to understand it. I'm trying to figure out what is going on below the surface here to make this state change happen.
Rayne
fair enough, I would've posted the definitions of get and put, but I guess thats been done.
barkmadley
That wouldn't have helped either. :pI had already looked at those definitions as deeply as possible, it it was that one crucial detail that was escaping my eyes. It isn't your fault, it's my fault for not being able to word a question correctly.
Rayne
+9  A: 

...How is puts updating the state in the first place? It seems to just be sitting there doing nothing...

Ah, now I understand your question. You're wondering how put (and get) work, right?

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;
}

I hope this illustrates that, while n doesn't change, the internal state still will get updated. If you execute tick() twice, the state will be incremented twice.

To get back to Haskell, here's the full definition of (the relevant parts) of the State monad:

newtype State s a = State { runState :: s -> (a, s) }

instance Monad (State s) where
    return a = State $ \s -> (a, s)
    m >>= k  = State $ \s -> let
        (a, r) = runState m s
        in runState (k a) r

get   = State $ \s -> (s, s)
put s = State $ \_ -> ((), s)

Now try to expand your tick example even further by manually inlining >>=, return, get and put. Hopefully it will get more clear how State works.

Tom Lokhorst
I beat you by a whole 5 seconds! It's odd how I tend to figure out things on my own /after/ I've asked the question. I appreciate the responses! :)
Rayne