为什么这些模式匹配重叠?

时间:2012-02-17 22:32:59

标签: haskell

为什么我的模式在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)。

1 个答案:

答案 0 :(得分:12)

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更难阅读,但如果你有更多的分支或需要做一些实际的模式匹配,那就没有意义。