函数定义的顺序在列表模式中是否重要

Does the order of function definition matter in list patterns

所以这些函数命令在 GHCI 中有不同的行为:

safetailpatter xs = tail xs
safetailpatter [] = []
safetailpatter [] = []
safetailpatter xs = tail xs

前者传入时产生如下警告和以下错误[]

ex3.hs:66:1: warning: [-Woverlapping-patterns]
    Pattern match is redundant
    In an equation for ‘safetailpatter’: safetailpatter [] = ...
*** Exception: Prelude.tail: empty list

因此定义的顺序很重要,为什么?我不明白为什么前者重叠而后者不重叠,因为给出了相同的定义。

xs 也匹配空列表,因此如果将 safetailpatter xs 放在第一个,safetailpatter [] 将永远不会被调用。

我对 Haskell 很陌生,但我认为这就是正在发生的事情。

所以,当你先放置 safetailpatter xs 然后用一个空列表调用它时,你试图在空列表上调用 tail,你得到了异常。

至于

Pattern match is redundant
    In an equation for ‘safetailpatter’: safetailpatter [] = ...

我认为这基本上就是我上面描述的意思,它抱怨声明是多余的,因为当你把后者放在第一位时,safetailpatter [] 已经被 safetailpatter xs 覆盖了。

这就是为什么您应该始终将 _ 放在模式匹配定义末尾的原因,否则您将永远不会调用其余模式:

myF (x:xs) = -- ....
myF _ = -- ...        -> Right
myF _ = -- ...        -> Wrong, now no the bellow definition will never get called
myF (x:xs) = -- ....

模式按顺序匹配。但是,这里发生的事情是您实际上并不是 safetailpatter xs 上的部分匹配。

在常规英语中 safetailpatter xs = tail xs 表示:任何变量上的 safetailpatter 是该变量的尾部

你要匹配的是:safetailpatter (x:xs) = tail (x:xs),它代表:safetailpatter 当应用于至少有一个元素的列表时,是这样一个列表的尾部

知道这一点,在代码中

safetailpatter xs = tail xs
safetailpatter [] = []

将按顺序检查,并且由于第一个等式与任何列表输入相匹配,您会在 [] 上得到 运行 时间错误。而

safetailpatter (x:xs) = tail xs
safetailpatter [] = []

按顺序匹配,由于 [] 不匹配第一个等式,它将 运行 第二个,没有 运行 时间错误

编辑

正如@chepner 所说,这是调用无可辩驳的模式。这意味着模式匹配正在发生,但没有失败的机会。与匹配 _

相同