## Example: Rolling dice

1.

```rollNDiceIO :: Int -> IO [Int]
rollNDiceIO n = replicateM n \$ randomRIO (1, 6)
```

## Dice without IO

1.

```rollDice :: StdGen -> ((Int, Int), StdGen)
rollDice g = ((n, m), g'')
where
(n, g')  = randomR (1, 6) g
(m, g'') = randomR (1, 6) g'
```

## Dice and state

1.

```-- A long version that matches the implementation of the previously shown rollDice function
rollNDice :: Int -> State StdGen [Int]
rollNDice n | n <= 0    = return []
rollNDice n = do
generator <- get
let (val, newGen) = randomR (1,6) generator
put newGen
vals <- rollNDice (n-1)
return (val:vals)

-- A much more concise version of the solution
rollNDice :: Int -> State StdGen [Int]
rollNDice n = replicateM n rollDie
where rollDie = state \$ randomR (1, 6)
```

2.

```-- For any monad, fmap = liftM = \f m -> m >>= return . f
-- In our case, we have:
fmap f pr = pr >>= return . f
-- Expanding (>>=):
fmap f pr = state \$ \ st ->
let (x, st') = runState pr st
in runState ((return . f) x) st'
fmap f pr = state \$ \ st ->
let (x, st') = runState pr st
in runState (return (f x)) st'
-- Expanding return:
fmap f pr = state \$ \ st ->
let (x, st') = runState pr st
in runState ((\ y -> state \$ (\z -> (y, z))) (f x)) st'
fmap f pr = state \$ \ st ->
let (x, st') = runState pr st
in runState (state \$ (\z -> (f x, z))) st'
-- runState and state undo each other:
fmap f pr = state \$ \ st ->
let (x, st') = runState pr st
in (\z -> (f x, z)) st'
fmap f pr = state \$ \ st ->
let (x, st') = runState pr st
in (f x, st')

-- Therefore:
instance Functor (State s) where
fmap f pr = state \$ \ st ->
let (x, st') = runState pr st
in (f x, st')

-- Alternatively, using the following helper function:
first f (x, y) = (f x, y)

fmap f pr = state \$ \ st -> first f (runState pr st)
fmap f pr = state \$ first f . runState pr

instance Functor (State s) where
fmap f pr = state \$ first f . runState pr
```

`fmap f pr` produces a state processor which runs `pr` and then applies `f` to the result `pr` gives back.

Note that, literally speaking, there is no value of type `a` inside `State s a`, as the latter is essentially just a function. Still, we can, through function composition, write an `fmap` instance which operates on the `a` values that will be produced by the state processor.

3.

```modify :: (s -> s) -> State s ()
modify f = state \$ \ st -> ((), f st)

gets :: (s -> a) -> State s a
gets f = state \$ \ st -> (f st, st)

-- Alternatively, using get and put:
modify f = get >>= \ st -> put (f st)

gets f = get >>= \ st -> return (f st)
-- Or simply (compare with exercise 2):
gets f = fmap f get
```