簡體   English   中英

為什么我們需要 Maybe Monad 而不是 Monad

[英]Why Do We Need Maybe Monad Over Either Monad

我在玩 Maybe 和 Either monad 類型(鏈接,根據返回值應用條件函數,還返回鏈接函數失敗的錯誤消息等)。 所以在我看來,我們可以通過使用 Either monad 來實現與 Maybe 相同且更多的事情。 所以我的問題是這些之間的實際或概念差異在哪里?

你當然是對的, Maybe aEither 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而不是“傳統預期”的簡單情況(主觀點,但是如果您獲得經驗,這幾乎可以)。

@phg 的回答很棒。 當我學習它們時,我會加入一些有助於我清除它的東西:

  • Maybe是一(價值)或無——即,你有一個價值或你什么都沒有
  • Either是一個邏輯析取,但你總是至少有一個(值) - 即,你有一個另一個,但不是兩者兼而有之。

Maybe非常適合諸如您可能有價值或可能沒有價值之類的事情 - 例如在列表中查找項目。 如果列表包含它,我們得到(Just x)否則我們得到Nothing

Either是代碼中分支的完美表示 - 它會以一種方式或另一種方式進行; LeftRight 我們用一個助記詞來記住它: Right就是正確正確)的方式; Left錯誤的方式(錯誤)。 這當然不是它唯一的用途,但絕對是最常見的。

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

好吧,你看,我們可以說所有產品類型都可以用 2 元組表示,所有非遞歸和類型都可以用Either來表示。 為了另外表示遞歸類型,我們需要一個固定點類型。

例如,當我們可以寫成(a, (b, (c,d)))(((a,b), c), d) ) 時,為什么還要有 4 元組(a,b,c,d) 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM