2012-02-17 73 views
1

爲什麼我的模式在do塊重疊內匹配?爲什麼這些模式匹配重疊?

(q, m) <- newRq 
let m2 = appendMsg "first" key m 
    (q4, m4) = case m2 of 
       m -> deleteRec key q m2 
       _ -> (q, m2) 

這將編譯與警告

Warning: Pattern match(es) are overlapped 
     In a case alternative: _ -> ... 

和我想不工作。看起來對於(q4,m4)它總是返回

[], fromList [] 

無視m2和m的值是什麼。有沒有我不指望他們的地方變量?

我想達到的目的是:如果m2和m相等,那麼(q4,m4)應計算爲deleteRec key q m2,否則爲(q,m2)。

回答

11

casem)中的第一個模式匹配所有內容並將其指定給m。第二個匹配所有東西並丟棄它(_),但沒有什麼可以匹配的,因爲m會得到一切。

我認爲你的意思的情況下像一個switch聲明的工作,但它的實際工作爲一組模式,很像一個函數聲明。所以你case是一樣一樣的東西:

check m2 
    where check m = deleteRec key q m2 
     check _ = (q, m2) 

在這段代碼中,你可能最好關閉只是使用if

if m == m2 then deleteRec key q m2 else (q, m2) 

您也可以考慮不同的縮進if聲明:

if m == m2 
then deleteRec key q m2 
else (q, m2) 

也應該工作。

然而,在一般情況下,你可以實際使用的保安在case聲明,所以這將工作太:

case m2 of 
    val | m2 == m -> deleteRec key q m2 
     | otherwise -> (q, m2) 

這顯然是難比if閱讀,但是如果你有多個分支機構或需要做一些實際的模式匹配,這是有道理的。

+0

真了,如果,但我只是坐在一小時,以避免它,因爲我經常閱讀,這不是地道的,並且在Haskell開發人員儘可能應該使用模式匹配。 – 2012-02-17 22:43:06

+3

是的,你*應該*儘可能使用模式匹配。但是不可能匹配變量的*值*。模式中的變量只是一個像「_」那樣的「洞」,可以帶任何東西;然後它將這個名字分配給那裏。 – 2012-02-17 22:43:50

+0

if-then-else還有其他選擇嗎? – 2012-02-17 22:44:29