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