The Monad Challenges

A set of challenges for jump starting your understanding of monads.


Set 1: Random Numbers

Set 2: Failing Computations

Set 3: Combinations

Set 4: Common Abstraction

Set 5: Do Notation

This project is maintained by mightybyte

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

More Generators

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 generate only even and odd numbers respectively and randTen generates only 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 the 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.


Play with a number of abstractions and try to find the most flexible. 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.

Previous Page - Next Page