2013-10-29 56 views
3

,我有以下构建在我的代码:简化嵌套也许模式匹配

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功能这一点,这不会使整个事情看起来好多了。有没有什么聪明的,但仍然可以理解的技巧可以使这种构造更“优雅”?

+2

你需要一个更好的结构问题,然后嵌套'Maybe' – Ankur

+0

这似乎有些奇怪哟你不在乎b和c的价值,只是他们是否有价值。这使得他们有效的布尔。 Maybes层是任意深度还是固定深度? – itsbruce

+0

你的模型基本上是错误的。你需要链接(即映射)函数/函子,而不是做这种强制性的风格。 – itsbruce

回答

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 

更新12

如果我们想有没有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 
+0

我不确定'Maybe' monad在这里会有什么帮助,'''有一种'Maybe(Maybe(Maybe ...))''',在每个'Maybe'层之后,我必须返回一个不同的如果它的计算结果为Nothing,(在上例中为'xyz')。 –

+0

@PhilipK哦,我看到我的错误:我已经更新了我的答案 – viorior

+0

这可以重写,以便f将任意大小的Eitherss列表作为单个参数。我认为会更好。但这是针对OP的评论,而不是你,viorior。 – itsbruce

12

为什么代码首先构造一个Maybe (Maybe (Maybe X))值?打开这样的价值并不好,但真正的问题是,为什么甚至有这样的价值。也许代码会更好地避免所有嵌套的Maybes。

如果你确实需要有这样的价值,并且需要在所有的案例中做不同的事情,你必须全部写下来。但是,相反的几个嵌套case语句,你可以将它们合并成一个大的模式匹配:

f Nothing    = x 
f (Just Nothing))  = y 
f (Just (Just Nothing)) = z 
f (Just (Just (Just d))) = d 
+0

我正在用大量“空”类型解析嵌套的JSON值,所以这就是为什么有这么多任意嵌套的“Maybes”。 –

8

尽管你的关于不使用maybe约束,我觉得这看起来相当不错:

f = maybe x (maybe y (maybe z id)) 

,甚至更好,如@pat建议在他的评论:

f = maybe x . maybe y . maybe z $ id 
+0

或'f =也许x。也许是。也许z $ id' – pat

+0

毫无意义的版本非常整洁! –