After reading a couple of tutorials on Haskell state monads I wanted to try them out myself. The tutorials I read claim that the Control.Monad.State provide the following defini
It doesn't exist any more. Unfortunately, this makes many Haskell resources on the web about it outdated.
To create a value, you can just use the state function:
state :: (s -> (a, s)) -> State s a
runState
, which used to be a field of State
, is now just a normal function itself, but it works in the same way as before.
State
has been rewritten in terms of the StateT
monad transformer:
type State s = StateT s Identity
StateT
itself has a constructor StateT
that functions very similarly to the old State
constructor:
newtype StateT s m a = StateT { runStateT :: s -> m (a, s) }
The only difference is that there is an extra parameter m
. This is just a slot where you can add in any other monad, which StateT
then extends with state-handling capabilities. Naturally, to regain the old functionality of State
, you just have to set m
to Identity
, which doesn't do anything.
newtype Identity a = Identity { runIdentity :: a }
A while ago the MTL switched from
newtype State s a = State ...
to
type State s = StateT s Identity
since otherwise we had to duplicate the logic for every monad and its transformer. Instead you can now use the state
function
state :: (s -> (a, s)) -> State s a
Sadly, RWH and LYAH both are out of date in this respect :(
I am working through Learn You A Haskell (LYAH), and I thought that I would post the working version of the example code found at http://learnyouahaskell.com/for-a-few-monads-more#state (Chapter 13, Section "Tasteful stateful computations")
The code that no longer works:
import Control.Monad.State
pop :: State Stack Int
pop = State $ \(x:xs) -> (x,xs)
push :: Int -> State Stack ()
push a = State $ \xs -> ((),a:xs)
The code modified to work:
import Control.Monad.State
pop :: State Stack Int
-- note the change from "State" to "state"
pop = state $ \(x:xs) -> (x,xs)
push :: Int -> State Stack ()
push a = state $ \xs -> ((), a:xs)
The "stackManip" function works as is:
stackManip :: State Stack Int
stackManip = do
push 3
a <- pop
pop