I have some ADT's each of which may or not contain another ADT. I need to retrieve data from lower levels and I'm writing some very repetitive code which I am sure can be eliminated. I've looked at some example code in Real World Haskell and in "Learn You a Haskell For Great Good" but I can't quite figure it out. Here is an example with irrelevent details of the ADT's left out.
T24Report
- projTitle :: Maybe ProjectTitle
- zip :: Maybe String
To retrieve the zip code from StreetAddress I've been ending up with this:
projNameStr :: T24Report -> String
projNameStr t24 = if isNothing projTitleMaybe
then ""
else (fromMaybe "") $ zip $ fromJust projTitleMaybe
where
projTitleMaybe = projTitle $ project t24
As the depth of the chain of objects increases, the repetitiveness of the code does too. There must be a better way. Ideas? References? I couldn't find a similar question on StackOverflow, but I believe it must be here...this seems like an simple problem that must have been asked.
Thanks, Tim
I'd write that, in the most generic case, something like:
projNameStr :: T24Report -> String
projName t24 = fromMaybe "" $ do
title <- projTitle $ project t24
zip title
The key point is using a do
block to factor out handling all of the Nothing
cases.
However, in this specific case, since there are only the two Maybe
s in the chain, I'd be tempted to shorten it a bit:
projNameStr :: T24Report -> String
projName t24 = fromMaybe "" $ projTitle (project t24) >>= zip
That's exactly what the previous example is converted to during compilation. Usually that sort of manual desugaring makes things worse, not better. But in this case, I would be tempted to go with this, just because it's a couple lines shorter and not too much more work to read.
Maybe's monad instance is built for solving this exact problem. If you have some objects, maybeX, maybeY and maybeZ with types Maybe a, Maybe b and Maybe c respectively, you can do this
do x <- maybeX
y <- maybeY
z <- maybeZ
return (x,y,z)
This will have the type Maybe (a,b,c), if any of the three Maybes was Nothing, the final result will be Nothing.
So, in your example, you would do something like this
projNameStr t24 = fromMaybe "" $ do t <- projTitle t24
zip t
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With