knick
knick

Reputation: 971

Where is the data constructor for 'State'?

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 definition:

newtype State s a = State { runState :: s -> (a,s) }  

However, I seem to be having trouble find the State data constructor:

Prelude> import Control.Monad.State
Prelude Control.Monad.State> :t State

<interactive>:1:1:
    Not in scope: data constructor `State'
    Perhaps you meant `StateT' (imported from Control.Monad.State)

I also tried a Hoogle search for State but did not find any data constructors with the expected type.

Where did the State constructor go? Did it ever exist? Or am I just looking in the wrong place? Essentially I would like to know what I need to do to create a state monad.

Upvotes: 28

Views: 3338

Answers (3)

TookieWookie
TookieWookie

Reputation: 382

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 

Upvotes: 8

daniel gratzer
daniel gratzer

Reputation: 53901

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 :(

Upvotes: 20

Tikhon Jelvis
Tikhon Jelvis

Reputation: 68152

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 }

Upvotes: 44

Related Questions