In this article, we’re going to describe one final monad. The `State`

monad is among the most common and most useful. We’ve seen the `Reader`

monad, which allows you to have a common global value among several functions. We also examined the `Writer`

monad, which allows you to keep adding to a particular monoid value. The `State`

monad combines these ideas to give us a full read-write state. We’ll see how this allows our code to have many of the qualities of other programming languages that Haskell seems to lack.

## Motivating Example: Monopoly

For this article, we’ll use a simple model for a Monopoly-like game. The main object is the `GameState`

data type containing several important pieces of information.

```
data GameState = GameState
{ players :: [Player]
, chanceDeck :: [GameCard]
, properties :: Map Property PropertyState
, piecePositions :: Map Player Property
. generator :: StdGen }
data PropertyState = Unowned | Owned Player
data ChanceCard = …
data Player = …
data BoardPostion = …
data GameAction = ...
```

Let’s think at a high level about how some of our game functions would work. We could, for instance, have a function for rolling the dice. This would **output** a number and **alter** our game’s number generator. We would then make a move based on the dice output and the current player. This would **change** the piece positions in the board state as well as leaving us with an **output action** to resolve (like drawing a card, or taking action on a property).

Buying a property also **changes** the board’s state. Drawing a chance card would **update** the state of the deck while **returning us** a `GameCard`

to resolve. We see a common pattern here among the different actions. Almost all of them will update `GameState`

in some way, and some of them will have an additional piece of output we’ll want to use.

## The State Monad

This is exactly the situation the State monad deals with. The State monad wraps computations in the context of **reading and modifying a global state object**. This context chains two operations together by determining what the state should be after the first operation, and then resolving the second operation with the new state.

It is parameterized by a single type parameter `s`

, the state type in use. So just like the Reader has a single type we read from, the `State`

has a single type we can both **read from and write to**.

The two main functions we’ll use within the `State`

monad with are `get`

and `put`

. They do exactly what you expect they’d do. The `get`

function works much like the `ask`

function of the reader monad, **retrieving our state value**. Meanwhile, `put`

works similarly to `tell`

in the `Writer`

monad, where we’ll pass an **updated state**. Finally we observe there will still be a final return type on each expression in `State`

, just as there is in any other monad. Thus our different function types will look like this for a return type of `a`

:

`State GameState a`

## Our Monopoly Functions

Now we can examine some of the different functions mentioned above and determine their types. We have for instance, rolling the dice:

```
rollDice :: State GameState Int
rollDice = do
currentState <- get
let gen = generator currentState
let (d1, gen') = randomR (1,6) gen
let (d2, gen'') = randomR (1,6) gen'
put (currentState { generator = gen'' } )
return (d1 + d2)
```

This **outputs** an `Int`

to us, and **modifies the random number generator** stored in our state! Now we also have the function making a move:

```
movePiece :: Player -> Int -> State GameState Property
movePiece player roll = do
currentState <- get
let currentPositions = piecePositions currentState
let currentPos = fromJust (M.lookup player currentPositions)
let next = nextProperty currentPos roll
let newMap = M.insert player next currentPositions
put (currentState { piecePositions = newMap } )
return next
nextProperty :: Property -> Int -> Property
...
```

This will give us the output of the new property we landed on, while also modifying the board with our new position of our piece. Based on the resulting position, we might take different actions, like drawing a chance card:

```
drawChance :: State GameState ChanceCard
drawChance = do
currentState <- get
let (fstCard : deck) = chanceDeck currentState
put (currentState { chanceDeck = deck } )
return fstCard
```

As we said above, this will **modify** the pile of available cards in the chance pile. There are other stateful functions we could describe, such as resolving a property purchase, or paying rent to another player. These would also exist within the state monad.

```
buyProperty :: Player -> Property -> State GameState ()
…
payRent :: Player -> Property -> State GameState ()
...
```

So finally, we can combine all these functions together with do-syntax, and it actually looks quite clean! We don’t need to worry about the side effects. The different monadic functions handle them. Here’s a sample of what your function might look like to play one turn of the game:

```
resolveTurn :: State GameState ()
resolveTurn = do
currentState <- get
let playerToMove = currentPlayer currentState
roll <- rollDice
newProperty <- movePiece playerToMove roll
action <- actionForProperty playerToMove newProperty
resolveAction action
switchNextPlayer
return ()
```

Obviously, we haven’t described all these functions, but the general idea should be clear. They would all exist within the state monad.

## State, IO, and Other Languages

When thinking about Haskell, it is often seen as a restriction that we **can’t have global variables** we can modify, like you could with Java class variables. However, we see now this isn’t true. We could have a data type with **exactly the same functionality** as a Java class, where many functions can modify the global state of the class object using the `State`

monad.

The difference is in Haskell we simply put a label on these types of functions. We don’t allow it to happen for free. We want to know **when side effects can potentially happen**, because knowing when they can happen makes our code easier to reason about. In a Java class, many of the methods won’t actually need to modify the state. But they **could**, which makes it harder to debug them. In Haskell we can simply make these pure functions, and our code will be simpler.

IO is the same way. It’s not like we **can’t perform IO in Haskell**. Instead, we want to label the areas where we can, to **increase our certainty** about the areas where we don’t need to. When we know part of our code cannot communicate with the outside world, we can be far more certain of its behavior.

## Summary

The State monad allows us to have a **global readable and writable state**. It gives Haskell exactly the kind of flexibility you expect to find in any other programming language. But by **separating stateful code** from our pure code, our pure code becomes **much easier to reason about**.

Since we have so many monads under our belts now, the next step is to know how to combine them. Next week we’ll talk about monad transformers, and how those enable us to use multiple monadic functionalities together!

If this has piqued your curiosity for Haskell but you don’t know where to begin, checkout out our checklist to learn more!

If this has inspired you to try out some Haskell code, be sure to try out our free workbook on recursion and higher order function. It includes 10 practice problems so you can hone your skills!