Where is the data constructor for 'State'?

后端 未结 3 521
南笙
南笙 2021-02-12 07:15

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

相关标签:
3条回答
  • 2021-02-12 07:51

    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 }
    
    0 讨论(0)
  • 2021-02-12 07:58

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

    0 讨论(0)
  • 2021-02-12 08:10

    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 
    
    0 讨论(0)
提交回复
热议问题