Simplifying nested Maybe pattern matching

余生长醉 提交于 2020-01-13 05:21:08

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!