Haskell/Solutions/Understanding monads

Random Number Generation
2. Using,   and   as defined in the chapter: rollNDice :: Int -> Seed -> ([Int], Seed) rollNDice 0 seed = ([], seed) rollNDice n seed = let (die, seed0) = rollDie seed (rest, seed1) = rollNDice (n-1) seed0 in ((die : rest),                         seed1) The function gains the first die and seed and then recursively calls itself to roll N number of die which, once  reaches the base case, in turn builds up a list of die. The function then returns the list of die and the final seed that was passed to the base case,.

3. We use mkStdGen to get the computer's random number generator and we give it an arbitrary number, 232. Firstly with  at the top of your file:

type Seed = StdGen

rollDie1 :: Seed -> (Int, Seed) rollDie1 seed = randomR (1,6) seed

In Prelude:

Main> rollDie1 (mkStdGen 232) (3,1017593109 40692)

Threading the State with bind
1. You have seen everything below the definition of  before. So everything up to that point is just there to set everything up. I've named >>=  and return   because this chapter uses bind and return to deal with random numbers specifically; whereas the real bind and return are more generalised and thus do not work for reasons that are somewhere over -> there. At least it works; what more do you want from me? Blood?

With  at the top of your file:

type Seed = StdGen type Random1 a = Seed -> (a, Seed)

rollDie :: Random1 Int rollDie seed = randomR (1,6) seed

(>>==) :: Random1 a -> (a -> Random1 b) -> Random1 b (>>==) m g = \seed0 -> let (result1, seed1) = m seed0 (result2, seed2) = (g result1) seed1 in (result2, seed2)

return1 :: a -> Random1 a return1 x = \seed0 -> (x, seed0)

rollNDice1 :: Int -> Random1 [Int] rollNDice1 0 = return1 [] rollNDice1 n = rollDie >>== (\d1 -> rollNDice1 (n-1) >>== (\rest -> return1 (d1 : rest)))

In prelude:

([4,3,1,1,2,3,5,4,2,5,6,4,6,2,4,5,6,5,1,5],1927676552 238604751)
 * Main> rollNDice1 20 (mkStdGen 231)

In case you're wondering: You pass  to rollNDice1 because   on its own only creates a  ; you need to pass the newly formed   a seed, in the form of , to get it shooting out random numbers.

Input/Output needs bind
1. putString :: String -> IO putString [] = putChar '\n' putString (s:xs) = putChar s >> putString xs

The State Monad
(State a) >>= f = State $ \s -> let (a',s') = a s                                    (State b) = f a'                                 in b s'

a >>= f = State $ \s -> let (a',s') = runState a s                        in runState (f a') s'