2016-04-20 54 views
4

由於Maybe類型與一組null和singleton列表是同構的,爲什麼有人想要使用Maybe類型,我可以使用列表來容納缺失?爲什麼我會想用Maybe而不是List?

+0

一個地方尋找潛在的動機,爲什麼我們關心的區別同構類型就是爲什麼人們使用和關心'newtype'。 – badcook

+6

我會問:「你爲什麼會在你需要一個'Maybe'時使用一個列表?」 '也許'更具體,並且許多錯誤都被阻止,因爲你甚至不能寫錯誤的代碼。它還使您的意圖在類型簽名中更加清晰。我真的不能相信一個好處了我的情況下,你可以使用'Maybe'(也許除了作爲一個非常簡短的中間形式),用列表的頭頂。是什麼促成了這個問題 –

回答

8

基於現有的(和正確的)答案,我會提到一個類型爲基礎的答案。

不同類型傳達不同的意圖 - 返回Maybe a代表與失敗而[a]可以代表非確定性(或者,簡單來說,多個可能的返回值)的方法可行的計算。

這樣做的原因在於不同類型對於類型類具有不同的實例 - 並且這些實例迎合類型傳遞的基本本質。以Alternative及其運營商(<|>)表示在給定的參數之間組合(或選擇)的含義。

  • Maybe a合併計算,可以失敗只是意味着在拍攝第一,是不是Nothing
  • [a]合併兩次計算,每有多個返回值只是意味着連接所有可能的值加在一起。

然後,取決於你的函數使用哪種類型,(<|>)將表現不同。當然,你可能會認爲你不需要(<|>)或類似的東西,但是你錯過了Haskell的主要優勢之一:它是許多高級組合庫。

作爲一般規則,我們喜歡我們的類型儘可能舒適和直觀。這樣,我們不是在與標準庫進行鬥爭,我們的代碼更具可讀性。

+0

作爲一個具體的例子,'只要x ==只是==只是x',但是'[x] <|> [y] == [x,y]'。 – chepner

+1

這看起來不是一個理想的例子,因爲如果(像OP一樣)你只關注列表頭部,它們的行爲就會類似。我現在想到的例子是'Monoid',但這是一個糟糕的例子,因爲'Monoid(Maybe a)'實例設計錯了。 – dfeuer

+0

@dfeuer是的,這個例子可能會更好。我無法想到其他任何簡單的事情('Functor','Applicative','Monad'表現相同的方式,'Monoid'也需要另一個'Monoid')。如果你有更好的主意,請評論它! – Alec

3

因爲有無限數量的可能列表以及Maybe類型的有限數量的可能值。它完美地代表了一件事,或者沒有任何其他可能性的事物的缺席。

14

因爲如果你對圖案[][x]這不是一個詳盡的匹配匹配列表,你會得到一個警告有關,迫使你要麼添加永遠不會被調用或忽略警告另一種情況。

然而,匹配MaybeNothingJust x是詳盡無遺的。所以如果你不符合其中一種情況,你只會得到一個警告。

如果您選擇的類型只能表示您可能實際生成的值,那麼您可以依靠非詳盡性警告來告訴您有關代碼中的錯誤,因爲您忘記檢查給定的情況。如果您選擇更多的「寬容」類型,您將永遠必須考慮警告是代表實際錯誤還是僅僅是不可能的情況。

+0

是的,你可以完全自由地忽視警告,並且使用非詳盡模式的「任務」(如果它們不是詳盡的域名,則不能稱之爲功能/地圖)。然而,你會使用Maybe類型的情況是那些(從我所見過的),它可以輕鬆或輕鬆地保證使用非映射分配不會讓你陷入困境。 – Tshimanga

+0

這就是說,我還是一個萌芽的haskeller,所以我的經驗可能還沒有擴展到這樣的問題情況 – Tshimanga

+3

@Tshimanga當你*可以*忽略這些警告時,通常有用的是編寫完全在他們的域中的函數,尤其是當用一個公開的API(例如一個包)寫一些東西; '也許'有助於編寫語義上有意義的代碼來實現這一目標。 – Jules

11

您應該努力獲得準確的類型。 也許表示只有一個值或沒有值。許多命令式語言通過值null代表「無」情況。

如果您選擇的是列表而不是也許,那麼您的所有函數都將面臨有可能獲得具有多個成員的列表的可能性。也許其中很多隻會被定義爲一個值,並且在模式匹配時不得不失敗。通過使用或許,您完全避免了一類運行時錯誤。

4

Lisp,Scheme,Python,Ruby,JavaScript等,每個都只處理一種類型,你可以用一個大的和類型在Haskell中表示。處理JavaScript(或其他)值的每個函數都必須準備好接收數字,字符串,函數,文檔對象模型的一部分等,如果出現意想不到的情況,則會拋出異常。用Haskell等類型語言編程的人更喜歡限制可能發生的意外事件的數量。他們還喜歡使用類型來表示想法,使得類型有用(和機器檢查)文檔。類型越接近表示意圖的含義,它們就越有用。

+0

我的想法,正是如此。 – chi

2

幾個答案在這裏提到詳盡性作爲一個因素。我認爲這是一個因素,但不是最大的一個,因爲有一種方法可以始終如一地對待名單,如果他們Maybe s,這將listToMaybe功能說明:

listToMaybe :: [a] -> Maybe a 
listToMaybe [] = Nothing 
listToMaybe (a:_) = Just a 

這是一個詳盡的模式匹配,哪些規則排除任何直接的錯誤。

我強調的更重要的因素是,通過使用更精確地模擬代碼行爲的類型,可以消除在使用更普通的替代方法時可能會發生的潛在行爲。舉個例子,你在你的代碼中使用a -> [b]這種形式的類型,儘管唯一正確的選擇(根據程序的規範)是空的或單例列表。嘗試努力,你可能會強制執行,這方面應遵守該規則的公約,它仍然有可能,你會陷入困境和:

  1. 不知怎的,在這種情況下使用的功能會產生兩個或兩個以上的列表項目;
  2. 不知怎麼使用在這種背景下產生的結果將觀察名單是否有兩個或多個項目,在這種情況下,不正確的行爲的功能。
    • 例如:一些預計不會超過一個值的代碼會盲目地打印列表中的內容,因此只打印一個應打印的項目時會打印多個項目。

但是如果你使用Maybe,那麼真的必須是一個值或沒有,編譯器強制執行此。

0

即使是同構的,例如,由於搜索空間的增加,QuickCheck將會運行得更慢。

相關問題