2013-10-29 168 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

毫無意義的版本非常整潔! –