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 that we have identified a pattern that we want to abstract, we need to formalize it somehow. When we did an abstraction like this before, we took a repeated type signature expression and created a shorthand name for it with a type synonym and a type variable. The modification only affected type signatures and had nothing to do with the implementations. Now we are trying to find commonalities across two implementations of completely different problems, so a simple type synonym is not going to be enough for what we want to do.
Clearly the random number example and the failing computation example have some similarities, but clearly they also have some differences. We’re trying to find the smallest set of fundamental primitives that have to be different. We have two candidates for those things: genTwo
/link
and generalB2
/yLink
. We just saw that generalB2
/yLink
can be written in terms of genTwo
/link
, so let’s assume that the genTwo
/link
abstraction is part of the fundamental set of primitives.
Whatever this pattern is that is common between random number generation and failing computations, we need to give it a name so we can talk about it more easily. Let’s call it a monad! You know how companies these days have been giving themselves nonsensical names that allow them to completely define their brand without competing with their customers’ preconceived notions of what common words mean? We’re doing the same thing here. (Well, mathematicians did it for us a while back.) Now that we have a name we need to create a type class:
class Monad m where
The generalized type signature for genTwo
/link
that you came up with in challenge #1 is one of the ones we want to put into our type class, and if you used the type variable m
, you should be able to drop it in. All we need is a name. Let’s use the name bind
.
Now that we have part of our type class your task is to create a single unified implementation for generalB2
/yLink
. Most of it should be the same, but you’ll find that there is one part that is different for the two. Make that part into the second function of the type class. Call this function return
. Figure out what the type signature should be. We’ve seen this pattern before in Set 1 and Set 3.