A set of challenges for jump starting your understanding of monads.
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
Now write a few more functions to generate different subsets of random numbers. But first, we need to generalize a bit. If we look at the type signatures for rand
and randLetter
, what are the commonalities?
rand :: Seed -> (Integer, Seed)
randLetter :: Seed -> (Char, Seed)
This common pattern can be captured in a type synonym. The key point here is that they use two different types, so you will have to introduce a type parameter. Create a type synonym that would allow us to change the type signatures of these two functions to the following:
rand :: Gen Integer
randLetter :: Gen Char
This is a relatively obvious type synonym and it is pretty easy to write, but it enables a big mental leap. Now that we have this type synonym we’ve jumped up a level of abstraction and higher level patterns will become more apparent. First go back and rewrite all your existing type signatures using this Gen
type synonym. Now write three new functions:
randEven :: Gen Integer -- the output of rand * 2
randOdd :: Gen Integer -- the output of rand * 2 + 1
randTen :: Gen Integer -- the output of rand * 10
Where randEven
and randOdd
only generate even and odd numbers respectively, randTen
only generates multiples of 10. Write randEven
in terms of rand
, write randOdd
in terms of randEven
, and write randTen
however you want. There’s a general pattern lurking here. If you implement all these functions the naive way like you did fiveRands
, you’ll be repeating the same pattern over and over. Figure out how to exploit the common pattern and write a function called generalA
that implements this pattern. All three of the above functions will also use generalA
. There are a number of different ways you could abstract this. We realize that you may not pick the right abstraction. Play around with as many different possibilities as you can think of.
SPEND SOME TIME WITH THIS BEFORE READING THE HINT!
Play with a number of abstractions and try to find the most flexible one. After you’ve spent some time with it, look at the hint here.
Pass all three of these functions a seed of 1. They’ll give you three numbers back, the product of which is 189908109902700.