我的代码中有以下构造:
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
我没有看到一种显而易见的方法来简化它,而不是使用嵌套的maybe
函数,这不会使整个事情看起来更好。是否有任何聪明 - 但仍然可以理解 - 的技巧有助于使这种结构更“优雅”?
答案 0 :(得分:12)
为什么代码首先构造Maybe (Maybe (Maybe X))
值?解包这样的值并不好,但真正的问题是,为什么甚至有这样的价值。也许代码会更好地避免所有嵌套的Maybes。
如果您真的需要拥有这样的价值并且需要在所有Just
/ Nothing
个案例中执行不同的操作,则必须将它们全部写下来。但是,您可以将它们组合成一个大模式匹配,而不是几个嵌套的case
语句:
f Nothing = x
f (Just Nothing)) = y
f (Just (Just Nothing)) = z
f (Just (Just (Just d))) = d
答案 1 :(得分:8)
尽管你没有使用maybe
,但我认为这看起来很不错:
f = maybe x (maybe y (maybe z id))
甚至更好,正如@pat在他的评论中所暗示的那样:
f = maybe x . maybe y . maybe z $ id
答案 2 :(得分:4)
更新2
Monad Either
适合你
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
更新3
如果我们想要没有Either
类型,我们可以重写函数:
import Data.Either(either)
either' = either id id
f :: Maybe (Maybe (Maybe d)) -> d
f a = either' $ maybeE x a
>>= maybeE y
>>= maybeE z