2017-03-02 52 views
11

我在玩Maybe和Monad類型(Chaining,根據返回值應用條件函數,還返回鏈接函數失敗等錯誤消息)。所以它對我來說似乎就像我們可以通過使用任一monad實現同樣的和更多的事情。所以我的問題是這些之間的實際或概念差異?爲什麼我們需要可能Monad在任一Monad

+0

我很震驚,這不是一個騙局。很好的問題。 –

回答

10

你當然是對的,Maybe a是同構於Either Unit a。問題是,他們往往在語義上用來表示不同的東西,有點像回到null和投擲之間的差異NoSuchElementException

  • Nothing/None表示「期待」丟失的東西,而
  • Left e表示無論出於何種原因,在獲取它時出現錯誤。

這就是說,我們甚至可以將二者結合起來的東西,如:

query :: Either DBError (Maybe String) 

我們表達缺失值(DB NULL)的兩種可能性,並在連接錯誤,DBMS ,或者其他什麼(不是說沒有更好的設計,但你明白了)。

有時,邊界是流動的;對於saveHead :: [a] -> Maybe a,我們可以說錯誤的預期可能性是按照函數的意圖編碼的,而像saveDivide可能編碼爲Float -> Float -> Either FPError FloatFloat -> Float -> Maybe Float,這取決於用例(再次,僅僅是一些愚蠢的例子...) 。

如果有疑問,最好的選擇是使用帶有語義編碼的自定義結果ADT(如data QueryResult = Success String | Null | Failure DBError),並優先選擇Maybe來處理「傳統期望」的簡單情況(主觀點,但是大多數都可以,如果你獲得經驗)。

5

@ phg的回答非常好。我會附和東西清除了起來,讓我當我學習他們:

  • Maybe是一個(價值)或無 - 也就是說,你有一個值,或者您有什麼
  • Either是邏輯分離,但你總是至少有一個(價值) - 即,你有另一個,但不是兩個。

Maybe適用於您可能有或沒有價值的地方 - 例如查找列表中的項目。如果列表中包含它,我們得到(Maybe x)否則我們得到Nothing

Either是在你的代碼分支的完美表現 - 它會去一個或其他方式; LeftRight。我們使用助記符來記住它:Right正確)的方式; Left錯誤方式(錯誤)。這當然不是,而是最常見的。

我知道這些差異起初看起來很微妙,但實際上它們適用於非常不同的事情。

+1

對於提及邏輯析取,你可以得到+1。這對於新來FP的人來說是非常平易近人的答案。 –

+0

謝謝Jared。您的反饋意味着我很多^ _ ^ – naomik

1

嗯,你看,我們可以把這個說得極端,說所有的產品類型都可以用2元組和所有的非遞歸和類型來表示,由Either。爲了額外表示遞歸類型,我們需要一個fixpoint類型。

例如,爲什麼有4元組(a,b,c,d)時我們還可以寫(a, (b, (c,d)))(((a,b), c), d)

或者爲什麼有列表,以下情況也適用?

data Y f = Y (f (Y f)) 

type List a = Y ((,) (Either() a)) 


nil = Y (Left(), undefined) 

cons a as = Y (Right a, as) 

infixr 4 cons 

numbers = 1 `cons` 2 `cons` 3 `cons` nil 

-- this is like foldl 

reduce f z (Y (Left(), _)) = z 
reduce f z (Y (Right x, xs)) = reduce f (f z x) xs 


total = reduce (+) 0 numbers