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.

Do Notation

Now that you’ve spent some time using the monad abstraction, you may have seen that while it does what we need, it’s a little more verbose than we would like. This is where Haskell’s do notation comes to the rescue. When you write the following do block:

rule1 = do
    foo <- calcFoo
    bar foo

GHC automatically desugars this to

rule1 = bind calcFoo (\foo -> bar foo)

It’s important to note what this says about the type signatures of everything involved.

rule1 :: m b
calcFoo :: m a
bar :: a -> m b

The key is that whatever m is, it must be the same for all three of these types. Also, calcFoo returns an m a, but bar takes a plain a. The bind function is responsible for “unboxing” the m a and passing the unboxed value to bar.

One thing that trips a lot of people up is what to do when they don’t have a function that looks like bar. The version of bar they want might instead have this type bar :: a -> b (note that here we’re specifically saying that bar’s type signature does NOT have an m). Figure out what to do in this situation.

Note this challenge isn’t concrete. We’re dealing with more abstract types that don’t have type signatures exactly the same as the ones you’ve been working with. We could have written this challenge in a concrete way, but we think it’s important to learn how to think in more abstract terms. So for this go back to the stuff you have done before and find something that you think can be written with the do block that rule1 has. Or better yet, make up a new function that does it using Maybe or Gen.

Previous Page - Next Page