我遇到了一個我認為可以更優雅地表達的模式:
我有兩個函式f1,f2 :: Int -> Int(它們的含義不相關),一個process :: Int -> Int執行以下操作:
- 如果
f1 x產生x1與 不同x,則重復該程序x1 - 否則,如果
f2 x產生x2與 不同x,則重復該程序x2 - 最后,停止行程并回傳
x
我的case ... of實作如下:
f1 :: Int -> Int
f1 = undefined
f2 :: Int -> Int
f2 = undefined
process :: Int -> Int
process x =
case f1 x of
x ->
case f2 x of
x -> x
x' -> process x'
x' -> process x'
產生以下警告:
so.hs:13:17: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: x' -> ...
|
13 | x' -> process x'
| ^^^^^^^^^^^^^^^^
so.hs:14:9: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: x' -> ...
|
14 | x' -> process x'
| ^^^^^^^^^^^^^^^^
任何人都可以闡明哪些模式是重疊的,以及如何process更優雅地實作?
uj5u.com熱心網友回復:
沒有辦法為“與我存盤在變數中的值相等的值”撰寫模式x。這是因為模式匹配是Haskell中創建變數的主要方式。
process :: Int -> Int
process x =
這x是一個模式。這是一個非常簡單的模式,因為它只匹配 的引數的任何可能值process,但您可以撰寫一個更結構化的模式,甚至多個方程來process匹配該引數1 的不同模式。并且在該模式匹配的范圍內( 的整個 RHS process),您將x作為參考匹配值的區域變數。
case f1 x of
x ->
這x又是一個模式,又是一個非常簡單的模式,匹配case運算式檢查過的任何可能的值。然后你有x一個新的區域變數,參考匹配范圍內的匹配值(->箭頭的 RHS 的所有內容);并且因為您創建了兩個同名的區域變數x,最區域的一個在它們都適用的范圍內遮蔽了另一個(因此您無法x在->箭頭的 RHS 中參考原始變數,只有新x的f應用于原始的結果x)。
這是您需要了解 Haskell 語法的內容。出現在模式中的變數總是創建一個新變數來參考與模式匹配的值;它永遠不會參考現有變數來檢查匹配的值是否等于。只有建構式會“檢查它們是否匹配”;變數只是系結到那里的任何東西。1
這同樣適用于您的 inner case,您打算在其中測驗結果以查看它是否仍然存在,x但實際上只是創建了一個新的x陰影兩個外部x變數。
這就是編譯器抱怨您的其他模式匹配是多余的原因。模式按順序檢查,每個模式中的第一個模式case已經匹配任何內容(并將其稱為x),因此每個模式中的第二個匹配case將永遠不會被嘗試。
因此,由于模式匹配永遠無法測驗值是否等于變數,因此您只需要使用模式匹配以外的構造即可!if ... then ... else ...會作業得很好。您也可以在模式上使用警衛。
1這實際上是我們區分以大寫字母開頭的建構式和以小寫字母開頭的變數之間的語法區別的核心原因!語言設計者希望一眼就能看出哪些詞是要匹配的建構式,哪些是要系結的變數,而不必考慮作用域中的所有建構式名稱。
uj5u.com熱心網友回復:
按照Ben的建議,我寫了以下內容:
process :: Int -> Int
process x
| x /= x1 = process x1
| x /= x2 = process x2
| otherwise = x
where
x1 = f1 x
x2 = f2 x
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/386987.html
下一篇:對引數應用函式x次的函式
