简化嵌套的Maybe模式匹配

Phi*_*sky 3 haskell nested pattern-matching simplify maybe

我的代码中有以下构造:

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
Run Code Online (Sandbox Code Playgroud)

我没有看到一种明显的方法来简化这个而不是使用嵌套maybe函数,这不会使整个事情看起来更好.是否有任何聪明 - 但仍然可以理解 - 的技巧有助于使这个结构更"优雅"?

sth*_*sth 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
Run Code Online (Sandbox Code Playgroud)


nic*_*kie 8

尽管你不使用约束maybe,我认为这看起来很不错:

f = maybe x (maybe y (maybe z id))
Run Code Online (Sandbox Code Playgroud)

甚至更好,正如@pat在他的评论中所说:

f = maybe x . maybe y . maybe z $ id
Run Code Online (Sandbox Code Playgroud)


vio*_*ior 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
Run Code Online (Sandbox Code Playgroud)

更新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
Run Code Online (Sandbox Code Playgroud)