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.

Chains of Failing Computations

In MCPrelude we have defined the following type synonym for you.

type GreekData = [(String, [Integer])]

We also provide two data structures greekDataA, greekDataB :: GreekData that have some sample data.

Write a function to query the above data structures. Your function should have the following type signature:

queryGreek :: GreekData -> String -> Maybe Double

Your implementation of this function should use the functions you wrote in the previous exercise to do the following: first query the GreekData that is passed in, look up the string passed in the second argument, and retrieve the corresponding list of Integers. Call this list xs. Next calculate the maximum of the tail of xs. (Don’t use any pattern matching here. Use case expressions and the maximumMay and tailMay functions you wrote in the last exercise.) Take the maximum and divide it by the head of the list (using your headMay and divMay functions). If any of these operations along the way return Nothing, then your function should return Nothing. But if everything succeeds, then return the final quotient. One hint… you’ll need to use the fromIntegral function to convert your two Integers to Doubles for the final call to divMay.

You will probably find this function pretty annoying to implement. Stick with us though… there is a point. The more you feel the pain now, the more the solutions will stick in your head later. Ultimately, we will get rid of the repeating part. But don’t jump ahead! We haven’t seen all patterns.

Your function should generate the following results:

queryGreek greekDataA "alpha" == Just 2.0
queryGreek greekDataA "beta" == Nothing
queryGreek greekDataA "gamma" == Just 3.3333333333333335
queryGreek greekDataA "delta" == Nothing
queryGreek greekDataA "zeta" == Nothing

queryGreek greekDataB "rho" == Nothing
queryGreek greekDataB "phi" == Just 0.24528301886792453
queryGreek greekDataB "chi" == Just 9.095238095238095
queryGreek greekDataB "psi" == Nothing
queryGreek greekDataB "omega" == Just 24.0

If your function threw any kind of exception on any of those inputs, then your implementation is wrong. Make sure your function always returns a Nothing or a Just in every case.

Previous Page - Next Page