考虑以下GHCi session :

$ ghci
GHCi, version 8.6.5: http://www.haskell.org/ghc/  :? for help
Prelude> :set -Wincomplete-patterns -Wincomplete-uni-patterns
Prelude> foo t | (_, _) <- t = "Foo"
Prelude> bar t | (_, _) <- id t = "Foo"
Prelude> baz x | Just _ <- x = "Yes" | Nothing <- x = "No"
Prelude> qux x | Just _ <- id x = "Yes" | Nothing <- id x = "No"

<interactive>:3:1: warning: [-Wincomplete-patterns]
    Pattern match(es) are non-exhaustive
    In an equation for ‘qux’: Patterns not matched: _
Prelude>

为什么GHC认为qux不完整?我们对id x的了解真的比对x的了解多吗?为何出于bar相同的原因,也不认为qux不完整?

举个更清晰的例子:
foo f x
  | Just _ <- f x = "Yes"
  | Nothing <- f x = "No"

bar f x = case f x of
  Just _ -> "Yes"
  Nothing -> "No"

据我所知,这些是完全等效的,但是前者会发出警告,而后者不会。

最佳答案

看起来,GHC在模式保护中不会将相同的表达式视为相同的值,除非该表达式是单个绑定(bind):

Prelude> f | Just x <- Just 1 = "foo" | Nothing <- Just 1 = "bar"

<interactive>:5:1: warning: [-Wincomplete-patterns]
    Pattern match(es) are non-exhaustive
    In an equation for ‘f’: Guards do not cover entire pattern space

这显然更加愚蠢,因为显然模式是详尽无遗的。它甚至不能分支。

我想说,即使这很奇怪,这可能也是做事的正确方法。它鼓励将表达式绑定(bind)到名称,这有助于确保仅对表达式求值一次。不过,这当然是一种绕行的方式。

至于为什么在bar中没有得到该错误,这是因为只有一对构造函数。您正在匹配id t的所有可能输出,即使它是一个计算表达式也是如此。没有其他匹配的构造函数。

10-07 16:10