由於Maybe類型與一組null和singleton列表是同構的,爲什麼有人想要使用Maybe類型,我可以使用列表來容納缺失?爲什麼我會想用Maybe而不是List?
回答
基於現有的(和正確的)答案,我會提到一個類型爲基礎的答案。
不同類型傳達不同的意圖 - 返回Maybe a
代表與失敗而[a]
可以代表非確定性(或者,簡單來說,多個可能的返回值)的方法可行的計算。
這樣做的原因在於不同類型對於類型類具有不同的實例 - 並且這些實例迎合類型傳遞的基本本質。以Alternative
及其運營商(<|>)
表示在給定的參數之間組合(或選擇)的含義。
Maybe a
合併計算,可以失敗只是意味着在拍攝第一,是不是Nothing
[a]
合併兩次計算,每有多個返回值只是意味着連接所有可能的值加在一起。
然後,取決於你的函數使用哪種類型,(<|>)
將表現不同。當然,你可能會認爲你不需要(<|>)
或類似的東西,但是你錯過了Haskell的主要優勢之一:它是許多高級組合庫。
作爲一般規則,我們喜歡我們的類型儘可能舒適和直觀。這樣,我們不是在與標準庫進行鬥爭,我們的代碼更具可讀性。
作爲一個具體的例子,'只要x ==只是==只是x',但是'[x] <|> [y] == [x,y]'。 – chepner
這看起來不是一個理想的例子,因爲如果(像OP一樣)你只關注列表頭部,它們的行爲就會類似。我現在想到的例子是'Monoid',但這是一個糟糕的例子,因爲'Monoid(Maybe a)'實例設計錯了。 – dfeuer
@dfeuer是的,這個例子可能會更好。我無法想到其他任何簡單的事情('Functor','Applicative','Monad'表現相同的方式,'Monoid'也需要另一個'Monoid')。如果你有更好的主意,請評論它! – Alec
因爲有無限數量的可能列表以及Maybe類型的有限數量的可能值。它完美地代表了一件事,或者沒有任何其他可能性的事物的缺席。
因爲如果你對圖案[]
和[x]
這不是一個詳盡的匹配匹配列表,你會得到一個警告有關,迫使你要麼添加永遠不會被調用或忽略警告另一種情況。
然而,匹配Maybe
與Nothing
和Just x
是詳盡無遺的。所以如果你不符合其中一種情況,你只會得到一個警告。
如果您選擇的類型只能表示您可能實際生成的值,那麼您可以依靠非詳盡性警告來告訴您有關代碼中的錯誤,因爲您忘記檢查給定的情況。如果您選擇更多的「寬容」類型,您將永遠必須考慮警告是代表實際錯誤還是僅僅是不可能的情況。
您應該努力獲得準確的類型。 也許表示只有一個值或沒有值。許多命令式語言通過值null代表「無」情況。
如果您選擇的是列表而不是也許,那麼您的所有函數都將面臨有可能獲得具有多個成員的列表的可能性。也許其中很多隻會被定義爲一個值,並且在模式匹配時不得不失敗。通過使用或許,您完全避免了一類運行時錯誤。
Lisp,Scheme,Python,Ruby,JavaScript等,每個都只處理一種類型,你可以用一個大的和類型在Haskell中表示。處理JavaScript(或其他)值的每個函數都必須準備好接收數字,字符串,函數,文檔對象模型的一部分等,如果出現意想不到的情況,則會拋出異常。用Haskell等類型語言編程的人更喜歡限制可能發生的意外事件的數量。他們還喜歡使用類型來表示想法,使得類型有用(和機器檢查)文檔。類型越接近表示意圖的含義,它們就越有用。
我的想法,正是如此。 – chi
幾個答案在這裏提到詳盡性作爲一個因素。我認爲這是一個因素,但不是最大的一個,因爲有一種方法可以始終如一地對待名單,如果他們Maybe
s,這將listToMaybe
功能說明:
listToMaybe :: [a] -> Maybe a
listToMaybe [] = Nothing
listToMaybe (a:_) = Just a
這是一個詳盡的模式匹配,哪些規則排除任何直接的錯誤。
我強調的更重要的因素是,通過使用更精確地模擬代碼行爲的類型,可以消除在使用更普通的替代方法時可能會發生的潛在行爲。舉個例子,你在你的代碼中使用a -> [b]
這種形式的類型,儘管唯一正確的選擇(根據程序的規範)是空的或單例列表。嘗試努力,你可能會強制執行,這方面應遵守該規則的公約,它仍然有可能,你會陷入困境和:
- 不知怎的,在這種情況下使用的功能會產生兩個或兩個以上的列表項目;
- 不知怎麼使用在這種背景下產生的結果將觀察名單是否有兩個或多個項目,在這種情況下,不正確的行爲的功能。
- 例如:一些預計不會超過一個值的代碼會盲目地打印列表中的內容,因此只打印一個應打印的項目時會打印多個項目。
但是如果你使用Maybe
,那麼真的必須是一個值或沒有,編譯器強制執行此。
即使是同構的,例如,由於搜索空間的增加,QuickCheck將會運行得更慢。
- 1. 使用mercurial爲什麼我會想合併而不提交?
- 2. 多態性:爲什麼使用「List list = new ArrayList」而不是「ArrayList list = new ArrayList」?
- 3. 爲什麼我的函數有時會返回(共享...)而不是(list ...)
- 4. Haskell String to Maybe List
- 5. 爲什麼Nil :: Nil會返回List(List())?
- 6. 爲什麼使用packed * args/** kwargs而不是傳遞list/dict?
- 7. 爲什麼Redis SortedSet使用Skip List而不是平衡樹?
- 8. 爲什麼會變成數字120而不是我想要的字符'x'?
- 9. Area.poly in R:爲什麼Shapefile轉換爲類「list」而不是「gpc.poly」?
- 10. 字符串被分割爲'list()'而不是'[]'爲什麼?
- 11. 如何指定我想在Modello中使用Set而不是List?
- 12. 爲什麼我會使用NSInvocation而不是Block?
- 13. 爲什麼我會使用Apache ServiceMix而不是ActiveMQ
- 14. 爲什麼我會使用白色屏幕而不是地圖?
- 15. 爲什麼Android Studio會告訴我使用getSupportActionBar()而不是getActionBar()?
- 16. 爲什麼我會使用wrappedPointCut而不是數據?
- 17. 爲什麼我會使用MockWebServer而不是WireMock?
- 18. 爲什麼我會使用check()而不是Match.test()?
- 19. 爲什麼Haskell的Prelude.read不會返回Maybe?
- 20. 傳遞Set [List [Int]]類型值而不是List [Int] - 爲什麼這會起作用?
- 21. 爲什麼ClassManifest需要Array而不是List?
- 22. 爲什麼len(list)而不是list.len()在python中?
- 23. 爲什麼我的JRadioButtons標籤是「...」而不是我想要的文本?
- 24. 爲什麼OCaml只有first :: rest on list,而不是rest :: last for list?
- 25. 想不通爲什麼ArrayList.add()是不是爲我工作
- 26. 使用Directory.GetDirectories(「c:\\」)時,爲什麼不能使用List <string>而不是string []?
- 27. 爲什麼我得到零而不是?
- 28. 爲什麼在Clojure中Maybe/Option的使用不那麼普遍?
- 29. 爲什麼head的返回值會隱式轉換爲Maybe?
- 30. 什麼使用,而不是會話?
一個地方尋找潛在的動機,爲什麼我們關心的區別同構類型就是爲什麼人們使用和關心'newtype'。 – badcook
我會問:「你爲什麼會在你需要一個'Maybe'時使用一個列表?」 '也許'更具體,並且許多錯誤都被阻止,因爲你甚至不能寫錯誤的代碼。它還使您的意圖在類型簽名中更加清晰。我真的不能相信一個好處了我的情況下,你可以使用'Maybe'(也許除了作爲一個非常簡短的中間形式),用列表的頭頂。是什麼促成了這個問題 –