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.
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
.
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
.