
I will just translate your example from Norvell's DIY state monad to GHC's ST monad. As you noticed, GHC's ST monad begins with an "empty" state and you use some commands to add state variables as you go. This means the translation is not straightforward. I hope you still get the gist of it. Your hunch is correct: Norvell's applyST becomes GHC's runST. Your example uses two state variables: a Char and an Int, paired up as a tuple. Below, I use one state variable of type (Char,Int) for that, as hinted by your first attempt at the translation. foo and bar will each need to take a parameter --- the reference to the state variable, due to the reference business. testfunc = do r <- newSTRef ('x',0) foo r bar r (c,n) <- readSTRef r return n foo r = do (c,n) <- readSTRef r writeSTRef r ('a', n+1) bar r = do (c,n) <- readSTRef r writeSTRef r (c,n+2) tryTestFunc = runST testfunc

Your example uses two state variables: a Char and an Int, paired up as a tuple. Below, I use one state variable of type (Char,Int) for that, as hinted by your first attempt at the translation. foo and bar will each need to take a parameter --- the reference to the state variable, due to the reference business.
testfunc = do r <- newSTRef ('x',0) foo r bar r (c,n) <- readSTRef r return n
Yeap, I could do it like this myself :) The whole problem is with passing the 'r' as a parameter, which is precisly what I'm trying to avoid. I think I already understood how to use this monad. Its pretty different from the monad state I was expecting, and as far as I can see, to be used in distinct situations. Thanks J.A.
foo r = do (c,n) <- readSTRef r writeSTRef r ('a', n+1)
bar r = do (c,n) <- readSTRef r writeSTRef r (c,n+2)
tryTestFunc = runST testfunc

Jorge's question raised a question in my mind. The IOExts module has many of the same features as the ST module, why are there two ways to do the same thing? Is the ST module only there for legacy purposes? Cheers, Theo Norvell

testfunc = do r <- newSTRef ('x',0) foo r bar r (c,n) <- readSTRef r return n
Yeap, I could do it like this myself :) The whole problem is with passing the 'r' as a parameter, which is
Hi, precisly
what I'm trying to avoid. I think I already understood how to use this monad. Its pretty different from the monad state I was expecting, and as far as I can see, to be used in distinct situations. If I understand you correctly, you want global mutable variables, right? This is, I believe, only possible using IORef's and unsafePerformIO. Something like this: | xRef :: IORef Int | xRef = unsafePerformIO $ | newIORef 0 | update_x :: IO () | update_x = do | x <- readIORef xRef | writeIORef xRef (x+1) (Sorry for formatting, I'm using Outlook now :-)
Of course this is not very functional, nice, safe or robust under compiler transformations (there probably should be a NOINLINE pragma there somewhere) Another option is to use implicit variables here. I haven't tested this approach yet, maybe somebody else on the list has? You don't need to pass the reference around, but if you're fond of explicitly giving types for top-level entities (as I am) you're stuck putting it in all type signatures affected (context-ellipsis would come in handy here!!) Cheers, Jan

If I understand you correctly, you want global mutable variables, right? This is, I believe, only possible using IORef's and unsafePerformIO.
Kind of, I'm searching for the best approach to keep track of data in my algorithms without constantly changing signatures. State monad as defined in the paper I mentioned "monads for the working haskell progarmmer" seemed the most elegant way. I saw ST in the Ghc and thought it was supposed to do the same... I never used mutable variables, but seems like it would prabably be the most efficient way to do it, as for more elegant, I don't know... I'm thinking about going for a simple State monad, no mutable variables... probably will face some efficiency problems though...
Something like this: | xRef :: IORef Int | xRef = unsafePerformIO $ | newIORef 0 | update_x :: IO () | update_x = do | x <- readIORef xRef | writeIORef xRef (x+1)
(Sorry for formatting, I'm using Outlook now :-)
Of course this is not very functional, nice, safe or robust under compiler transformations (there probably should be a NOINLINE pragma there somewhere)
And I was trying to get away from unsafePerformIO... :-) J.A.
participants (4)
-
Albert Lai
-
Jan de Wit
-
Jorge Adriano
-
Theodore Norvell