为什么身份函数有时会改变模式是否详尽无遗?
Why does the identity function sometimes change whether patterns are exhaustive?
考虑这个 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
不完整?我们真的比 x
更了解 id 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 不会将相同的表达式视为模式保护中的相同值,除非表达式是单个绑定:
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
这更愚蠢,因为很明显模式是详尽无遗的。它甚至不能分支。
我想说这可能是正确的做事方式,即使它很奇怪。它鼓励将表达式绑定到一个名称,这有助于确保表达式只被评估一次。不过,这当然是一种迂回的方式。
至于为什么您在 bar
中没有收到该错误,那是因为对只有一个构造函数。您正在匹配 id t
的每个可能输出,即使它是一个计算表达式。没有您不匹配的替代构造函数。
考虑这个 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
不完整?我们真的比 x
更了解 id 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 不会将相同的表达式视为模式保护中的相同值,除非表达式是单个绑定:
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
这更愚蠢,因为很明显模式是详尽无遗的。它甚至不能分支。
我想说这可能是正确的做事方式,即使它很奇怪。它鼓励将表达式绑定到一个名称,这有助于确保表达式只被评估一次。不过,这当然是一种迂回的方式。
至于为什么您在 bar
中没有收到该错误,那是因为对只有一个构造函数。您正在匹配 id t
的每个可能输出,即使它是一个计算表达式。没有您不匹配的替代构造函数。