Reputation: 889
I want to write a function that takes two Maybe Int
parameters and returns the minimum of them if they are both Just number
, and 'the other' if either of them is Nothing
. I'm not satisfied with my first attempt:
maybeMin :: Maybe Int -> Maybe Int -> Maybe Int
maybeMin Nothing arr = arr
maybeMin ell Nothing = ell
maybeMin ell@(Just l) arr@(Just r) = if l < r then ell else arr
As an optimisation I don't want to create a new value in the third case; i.e., I don't want to write
maybeMin ell@(Just l) arr@(Just r) = Just $ if l < r then l else r
The above code seems clunky and it seems to me that I ought to be able to exploit the fact that Maybe
is an instance of Functor
, Applicative
or Monad
. However, my best attempt to go higher-order doesn't do the same thing:
maybeMin ell arr = ell >>= (\l -> arr >>= (\r -> if l < r then ell else arr))
because it will return Nothing
if either operand be Nothing
.
Is there an elegant way to do what I want?
Upvotes: 2
Views: 61
Reputation: 3924
You looked at Functor
, Applicative
, and Monad
, but you may want to check out Alternative
. As an example of its use, Just 3 <|> Nothing
will yield Just 3
and not Nothing
.
For your particular use, if you want a one-liner, you could try:
maybeMin l r = min l r <|> l <|> r
Just to break that down, we first calculate min l r
, which uses the Ord
instance of Maybe
to give the minimum of l
and r
if both are Just
values. If this works, then the computation stops there, but if either one isn't Just
, then we check to see if l
is a Just
value. If it is, then that is the result, and if not, we end up returning r
as the result.
Upvotes: 8