The Monad Challenges

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

Outline

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.

Generalizing Random Pairs

Use the provided rand function and your randLetter function to make a function that generates a random pair of a Char and an Integer.

randPair :: Gen (Char, Integer)

Generate the letter first, then generate the number using the seed acquired from generating the letter. When you give this function (mkSeed 1) it gives you the random pair ('l',282475249).

Here we’re starting to see the Gen type synonym pay off. Without Gen, the type would have been:

randPair :: Seed -> ((Char, Integer), Seed)

Still understandable, but the nested tuples are starting to obscure things slightly.

You have just composed two generators. Now generalize the composition to generalPair, and make sure that the second argument receive the seed generated by the first argument.

generalPair :: Gen a -> Gen b -> Gen (a,b)

This function makes the Gen type synonym almost essential. Here’s what we would have had to write if we didn’t have Gen:

generalPair :: (Seed -> (a, Seed)) -> (Seed -> (b, Seed)) -> (Seed -> ((a,b), Seed))

Removing the unnecessary parentheses gets us this type signature, which might help you a little when implementing the function.

generalPair :: (Seed -> (a, Seed)) -> (Seed -> (b, Seed)) -> Seed -> ((a,b), Seed)

Write another version randPair_ using generalPair, and test it by comparing its output to what you got from randPair.

Generalizing Pairs Even More

This generalPair function can be generalized even more. Instead of always constructing pairs, you should be able to have a generalization that can construct anything. Your result shouldn’t be fixed to Gen (a,b). It should also be able to be Gen String, Gen Polynomial, or Gen BlogPost. All you need to do is pass in a function that does the constructing with two inputs. Call this even more generalized function generalB. Once you have it implemented, write a new generalPair2 function in terms of generalB.

Previous Page - Next Page