Reputation: 2967
I'm going through the state monad here and I'm trying to implement:
import Control.Monad.Reader
import Control.Monad.Writer
import Control.Monad.State
type Stack = [Int]
pop :: State Stack Int
pop = State $ (x : xs) -> (x, xs)
However I'm getting the following error:
"Data constructor not in scope:
State :: ([t0] -> (t0, [t0])) -> State Stack Int
Perhaps you meant one of these:
‘StateT’ (imported from Control.Monad.State),
variable ‘state’ (imported from Control.Monad.State)"
Am I missing something basic here?
Upvotes: 4
Views: 548
Reputation: 32319
No you aren't. The tutorial is simplifying things a bit (or maybe it is just outdated - I don't go far back enough to know which of the two) is outdated. Control.Monad.State
defines a monad transformer StateT
. It also exports a simpler type synonym equivalent to what the tutorial is teaching you
type State s a = StateT s Identity a
However, that does mean that the constructor isn't State
, it is StateT
(and it has a generalized signature). Thankfully, you won't need to worry too much about that for now.
State
, you can use the state
function and pretend it has the signature state :: (s -> (a,s)) -> State s a
(in reality, it has a more general signature - which you come across in error messages).State
, just use runState :: State s a -> s -> (a,s)
instead of pattern matching.From the example you gave:
import Control.Monad.Reader
import Control.Monad.Writer
import Control.Monad.State
type Stack = [Int]
pop :: State Stack Int
pop = state $ \(x : xs) -> (x, xs)
Upvotes: 9
Reputation: 92057
Why do you suppose that the interface to State a
is through a data constructor that wraps a function s -> (a, s)
? That is a simple way to implement State, but you are not provided that interface. Instead, use the constructs provided in Control.Monad.State.
One simple change is just to use the lower-case state
function designed for this purpose:
pop :: State Stack Int
pop = state $ \(x : xs) -> (x, xs)
Alternatively, instead of working with this low-level view of State, you can work with it as a monad through its put
and get
functions:
pop :: State Stack Int
pop = do
(x : xs) <- get
put xs
return x
Upvotes: 2