0

Reading through Learn You a Haskell, I'm trying to construct a Stack [Int] Int:

ghci>import Control.Monad.State

ghci> let stack = state ([1,2,3]) (1) :: State [Int] Int

<interactive>:58:20:
    Couldn't match expected type `s0 -> (State [Int] Int, s0)'
                with actual type `[t0]'
    In the first argument of `state', namely `([1, 2, 3])'
    In the expression: state ([1, 2, 3]) (1) :: State [Int] Int
    In an equation for `stack':
        stack = state ([1, 2, 3]) (1) :: State [Int] Int

How can I create a Stack [Int] Int?

Kevin Meredith
  • 41,036
  • 63
  • 209
  • 384
  • 2
    What are you trying to do with this function? The way I understand the `State` monad, you need to be doing something to change the state. – shree.pat18 Aug 18 '14 at 03:07
  • 1
    `State [Int] Int` is really just a function of type `[Int] -> (Int, [Int])`. It doesn't "contain" a `[Int]` or a `Int`. You can create a *computation* which represents ignoring the previous state, setting the state to `[1,2,3]`, and returning 1 with `put [1,2,3] >> return 1` or `state (\_ -> (1, [1,2,3])`. – user2407038 Aug 18 '14 at 03:20
  • The tutorial goes through many steps. Did you notice the type synonym `type Stack = [Int]`? Once the state monad is introduced, it starts dealing with `State Stack a` (for various choices of `a`). So it’s not a `Stack [Int] Int` you want. (Or perhaps those were typos.) – Luc Danton Aug 18 '14 at 05:48
  • Good straightforward answer from *user2407038*. There is no magic, just functions compound. Your example may be rewritten like `let sstack = state (\lst -> (sum lst, lst)) ; runState sstack [1,2,3,4]` results in `(10,[1,2,3,4])` . Your state is a list of numbers `:: [Int]` and monad is a function `sum` `:: [Int] -> Int` which returns state's sum `::Int`. In fact the parameter is a more generic `Num a` but used `Int` for briefness. – David Unric Aug 18 '14 at 11:16

1 Answers1

6

It depends on what you're trying to do. State s a is essentially a newtype for a certain kind of function type (specifically s -> (a, s)), so it doesn't really make sense to make a State value from just a list. The simplified (internal) definition of State looks something like

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

Though you won't use the State constructor directly, it does illustrate the fact that a State s a value consists of a function.

You need a function that updates the state in some way (which could be considered a "State action"), then you can use runState :: State s a -> s -> (a, s) to execute the provided State action, given a certain initial state (the s argument).

It looks like you want to use [1, 2, 3] as your initial state, but you do also need to provide that update function (which is what you use to construct the State s a value itself).

In the Learn You a Haskell example, the Stack type synonym represents the actual stack data while State Stack ... represents a stateful action on the Stack data. For instance, an action of type State Stack Int uses a Stack value as its state and results in an Int when it is executed.

David Young
  • 10,713
  • 2
  • 33
  • 47