
This thing is giving me fits. I need a global variable of sorts for an implementation of Syslog. (Yes, I really do.) It seems the right way to do that is the state monad. But I can't figure out how to do two simple things: * Read what is in there without modifying it * Modify it appropriately I looked at the examples in Control.State.Monad. We see: tick :: State Int Int tick = do n <- get put (n+1) return n Add one to the given number using the state monad: plusOne :: Int -> Int plusOne n = execState tick n Which looks nice enough, but completely useless. tick seems to be a very complex way to say ((+) 1) in this example. Oddly enough, I get a type error if I try this: tick :: Int -> State Int Int tick newval = do put newval return newval Or this: tick :: State Int Int tick = do n <- get return n That is even more incomprehensible to me -- why would removing a line before the return cause a type error?

On 2004-10-07, John Goerzen
This thing is giving me fits. I need a global variable of sorts for an implementation of Syslog. (Yes, I really do.)
OK, my problem is that I have been looking at the world wrong. I found what I really needed in Data.IORef. Which leaves me with an odd curiosity -- I still can't figure out how state monads are anything but syntactic sugar (and lead more to spaghetti code at that <g>) -- John

John Goerzen wrote:
Which leaves me with an odd curiosity -- I still can't figure out how state monads are anything but syntactic sugar (and lead more to spaghetti code at that <g>)
Perhaps because state monads = syntactic sugar. The state monad is just a nice(er) way of passing around some global state (Junk). Without state monads f :: Junk -> a -> (Junk, b) With state monads, f :: a -> State Junk b .... Though if some function doesn't need to 'modify' your Junk, you find yourself having to re-factor things like, decend :: Junk -> Exp -> Exp decend state (Node a t1 t2) = Node a (decend state t1) (decend state t2) into decend :: Exp -> State Junk Exp decend (Node a t1 t2) = do t1' <- decend t1 t2' <- decend t2 return $ Node a t1' t2' .. which IMHO is not as pretty. Ben.

Sorry to nit-pick, but state monads are NOT syntactic sugar -- they're just an example of good old data/functional abstraction, that also happens to be in the form of a monad. On the other hand, Haskell's "do" notation -- now THAT'S syntactic sugar :-) -Paul Ben Lippmeier wrote:
John Goerzen wrote:
Which leaves me with an odd curiosity -- I still can't figure out how state monads are anything but syntactic sugar (and lead more to spaghetti code at that <g>)
Perhaps because state monads = syntactic sugar.
The state monad is just a nice(er) way of passing around some global state (Junk).
Without state monads f :: Junk -> a -> (Junk, b)
With state monads, f :: a -> State Junk b
.... Though if some function doesn't need to 'modify' your Junk, you find yourself having to re-factor things like,
decend :: Junk -> Exp -> Exp decend state (Node a t1 t2) = Node a (decend state t1) (decend state t2)
into
decend :: Exp -> State Junk Exp decend (Node a t1 t2) = do t1' <- decend t1 t2' <- decend t2
return $ Node a t1' t2'
.. which IMHO is not as pretty.
Ben.

G'day all.
Quoting Paul Hudak
Sorry to nit-pick, but state monads are NOT syntactic sugar -- they're just an example of good old data/functional abstraction, that also happens to be in the form of a monad.
Right. State monads help to future-proof your code because you don't have to change very much when you find that you need state _and_ something else (e.g. I/O). Cheers, Andrew Bromage
participants (4)
-
ajb@spamcop.net
-
Ben Lippmeier
-
John Goerzen
-
Paul Hudak