我目前正在學習 Haskell,碰到了這個運算式。
statement
case 1 ′div′ 0 of _ -> 42
我的直覺是,由于除以0,這將導致運行時錯誤,但從測驗來看,情況并非如此。
我的結論是,這一定是由于 Haskell 內部的惰性評估。那是因為_任何東西的匹配都不會檢查它的比較?
所以如果有人能告訴我這個評估是否正確,如果不是為什么。還請詳細說明在不實際查看運算式的情況下案例行可以匹配的前提。
uj5u.com熱心網友回復:
您的分析是準確的,但這實際上非常繁瑣。這并不復雜,但需要仔細考慮非常精確的問題。
在哈斯克爾
案例運算式具有一般形式
case exp0 of {pat1 -> exp1 ; ...}
當 case 運算式被評估時,exp0被評估得足夠遠以確定它是否匹配pat1。如果是這樣,則 case 運算式將使用為其創建的exp1任何附加系結進行計算。pat1如果不匹配,它會進入下一個模式或保護并重復。(如果不匹配,則評估為例外。)
值得注意的是,您的第一個替代方案無需任何評估即可匹配所有內容。所以不執行評估div 1 0。該模式不系結任何東西,然后 case 運算式的計算結果為 42。
這與您已經完成的情況不同:
case 1 `div` 0 of
0 -> 42
_ -> 42
在這種情況下,div必須計算運算式以查看它是否等于 0。這會導致例外,這將成為整個 case 運算式的結果。即使兩個分支具有相同的值也是如此。模式的內容對于確定與嚴格性相關的行為非常重要。
在核心
GHC Haskell 編譯器是迄今為止最常見的編譯器,它有一個稱為“核心”的中間表示,它看起來類似于 Haskell,但型別類和大多數語法糖完全脫糖。Core 的語意也與 Haskell 略有不同,尤其是在其 case 構造方面。在核心中,大小寫總是會導致對頂級建構式的評估。使用嵌套重寫模式以匹配原始 Haskell 代碼的模式語意。
本節是一個旁白,但如果你曾經研究過優化 Haskell 代碼,你會遇到核心問題,知道存在差異是很有用的。
uj5u.com熱心網友回復:
我的結論是,這一定是由于 Haskell 內部的惰性評估。那是因為
_任何東西的匹配都不會檢查它的比較?
對,就是這樣!
在模式匹配期間,評估只執行匹配模式中的建構式(和數字/字符文字)所需的次數。如果模式是變數或通配符_,則不需要評估。
case undefined of _ -> () -- OK
case undefined of True -> () -- crash
case undefined of (_,_) -> () -- crash
case (undefined, 4) of (_,x) -> x 1 -- OK
此外,模式匹配從左到右、從上到下進行:
case (4, undefined) of
(3, True) -> 1
(4, _) -> 2
評估為2- 我們首先匹配4反對3,然后在我們嘗試匹配undefined反對之前失敗True。通過這種方式,我們避免了崩潰,并且第二種模式(4, _)成功了。
(要詳盡:實際上有一個例外。如果您對newtype建構式進行模式匹配,則不會發生評估。您可以暫時忽略這種情況,因為您正在學習——它并不常見。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/487868.html
