2016-06-13 54 views
1

哈斯克爾擁有安全語言的聲譽。一般來說,一個可能的編程錯誤會導致編譯時錯誤,而且會減少運行時間。爲什麼在Haskell case語句中默認的catch-all不是強制的?

其中一個例子是if表達式。 if中的else始終是強制性的。你需要掩蓋兩種可能性。這很好,因爲你已經想到並且覆蓋了運行時會發生什麼的所有可能性。

Now Haskell has a case expression。 (這與OO和命令式語言中的switch語句有一些相似之處 - 但Haskell在類型系統中增加了很多豐富性)。

describeList :: [a] 
describeList xs = "The list is " ++ case cs of [] -> "empty." 
               [x] -> "a singleton list." 
               xs -> "a longer list." 

但是對於case表達式,默認的「全部捕獲」不是強制性的。

對我來說,這聽起來像會導致運行時錯誤。

我的問題是:爲什麼在Haskell case聲明中默認的捕獲全部不是必需的?

+0

你可以寫'_ - >錯誤「永遠不會發生」,但這是默認行爲。重點是什麼? –

+4

你最後的模式'xs - >「...」'**已經是一個全部捕獲 - 所以是問題*爲什麼*你不是被迫使用'_'或者它是爲什麼當你不匹配所有不是一個錯誤? – Carsten

+2

要問的一個更好的問題可能是:*爲什麼Haskell中的模式匹配可能是非詳盡的?*因爲如果明確地涵蓋了所有的情況,那麼catch-all將是超級的,甚至是有害的。 – stholzm

回答

6

Haskell肯定是更安全比許多其他語言,特別是主流的,但它遠不是100%安全。 Haskell中的其他不安全功能還包括編寫無限循環的功能,如let x = x in xunsafePerformIOerrorundefined。我想你可以說這只是方便和安全之間的折衷。

在比您的簡單示例更復雜的代碼中,有時會出現一些您知道不會發生的情況,因此您將它們從case表達式中排除,但Haskell的類型系統不夠強壯,無法編譯器能夠知道這些失蹤案件是不可能的。 (例如,你可能正在計算一些數學函數,它只能返回數字3,45,但這個事實是由於你碰巧知道的一些困難的定理以及編譯器不知道的。)

對於它的價值,您可以將-fwarn-incomplete-patterns傳遞給ghc編譯器,以便在編譯時即使在缺少case語句中的某個分支的情況下也會收到警告。這包含在-W選項中,它打開了幾個常見的編譯器警告。

+0

另一個可能的答案:GADTs使(聲音和完整)窮盡檢查不可判定 –

+0

也是如此!雖然我認爲GADTs在做出決定時並不存在不要對Haskell中的case語句進行詳盡的檢查。 – kini

+2

不要忘記,' - 錯誤'可以有效地將該警告轉化爲錯誤,就像OP詢問的那樣。 –

3

總是不需要。如果明確地處理所有情況(模式匹配是窮盡),則永遠不會達到全部情況。

我可以想到一個強制性catch-all情況的嚴重缺點:如果擴展ADT(代數數據類型),依賴代碼仍然會編譯,程序員不會提醒他們應該處理額外的情況。

+0

是的 - 但這是一個評論,並沒有真正回答這個問題 – Carsten

+0

我不同意 - 這個答案提供了一個可能的解釋,爲什麼萬能的案件不是強制性的,通過解釋一種方法,如果它是強制性的,語言將更難正確使用,這聽起來像是對我的回答, – amalloy

+0

這回答了OP詢問的內容,但是我想知道它是否回答了OP想要詢問的內容,我不確定是否這裏的實際問題是「爲什麼非詳盡模式允許?」 – chi

相關問題