I’m trying to run one of the most simple examples from the Haskell online book where you implement a stateful function modeling a stack of numbers. The code from the example I’m using is (http://learnyouahaskell.com/forafewmonadsmore#state):
import Control.Monad.State
type Stack = [Int]
pop :: State Stack Int
pop = State $ \(x:xs) > (x,xs)
push :: Int > State Stack ()
push a = State $ \xs > ((),a:xs)
Yet when trying to load it in Prelude I get:
state.hs:6:7: error:
Data constructor not in scope:
State :: ([a0] > (a0, [a0])) > State Stack Int

6  pop = State $ \(x:xs) > (x,xs)
 ^^^^^
state.hs:9:10: error:
Data constructor not in scope:
State :: ([Int] > ((), [Int])) > State Stack ()

9  push a = State $ \xs > ((),a:xs)
 ^^^^^
Failed, no modules loaded.
What am I missing??? Is this example somehow wrong?
I was just expecting to simply load the module with no errors. No clue what is wrong.
>Solution :
Somewhat surprisingly, the Control.Monad.State
module does not contain a data constructor called State
. That would be the case if it simply defined
newtype State' s a = State { runState :: s > (a,s) }
– which it used to do in version 1 of the mtl
library, but doesn’t anymore. Since version 2.0, the module only exports a type synonym called State
, which is actually reexported from Control.Monad.Trans.State
and is implemented thus:
newtype StateT s m a = StateT { runStateT :: s > m (a,s) }
type State s = StateT s Identity
The Identity
monad makes this behave so that m (a,s)
is isomorphic to simply (a,s)
by itself, so in the end StateT s Identity a
is indeed isomorphic to State' s a
. It is however more general: StateT
is a monad transformer that can also be stacked on top of other monadic actions, such as IO
.
So you can’t use a State
value constructor, but you can use state
which behaves exactly as State
behaved in mtl1.1
. (Except you can’t pattern match on it, but you can still use runState
.)
pop :: State Stack Int
pop = state $ \(x:xs) > (x,xs)
push :: Int > State Stack ()
push a = state $ \xs > ((),a:xs)