问题
I have the following construct in my code:
f :: Maybe A -> X
f a = case a of
Nothing -> x
(Just b) -> case b of
Nothing -> y
(Just c) -> case c of
Nothing -> z
(Just d) -> d
I'm not seeing an obvious way to simplify this instead of using nested maybe
functions, which wouldn't make the whole thing look much better. Are there any clever - but still understandable - tricks that would help make this construct more "elegant"?
回答1:
UPDATED 2
Monad Either
is for you
import Data.Maybe (maybe)
maybeE :: e -> Maybe a -> Either e a
maybeE e = maybe (Left e) Right
f :: Maybe (Maybe (Maybe d)) -> Either e d
f a = maybeE x a
>>= maybeE y
>>= maybeE z
UPDATED 3
If we want to have not Either
type, we could rewrite function:
import Data.Either(either)
either' = either id id
f :: Maybe (Maybe (Maybe d)) -> d
f a = either' $ maybeE x a
>>= maybeE y
>>= maybeE z
回答2:
Why did the code construct a Maybe (Maybe (Maybe X))
value in the first place? Unpacking such a value isn't nice, but the real question is, why there even is such a value. Maybe the code would better avoid all those nested Maybes.
If you really need to have such a value and need to do different things in all the Just
/Nothing
cases you'll have to write them all down. But instead of several nested case
statements you could combine them into one big pattern match:
f Nothing = x
f (Just Nothing)) = y
f (Just (Just Nothing)) = z
f (Just (Just (Just d))) = d
回答3:
Despite your constraint about not using maybe
, I think this looks quite nice:
f = maybe x (maybe y (maybe z id))
or even better, as @pat suggests in his comment:
f = maybe x . maybe y . maybe z $ id
来源:https://stackoverflow.com/questions/19655870/simplifying-nested-maybe-pattern-matching