模式匹配期望非空列表的圆括号而不是方括号

Roh*_*rma 1 haskell

在Haskell中,为什么模式匹配期望列表具有圆括号,但是当它不为空时不支持方括号?当它尝试使用空列表[](方括号)进行模式匹配时,为什么它不遵循相同的约定.不应该专门为元组保留圆形括号吗?

例如 - 下面不起作用

third :: Integral a => [a] -> a
third xs = case xs of 
                      [] -> 0
                      [_:_:x:_] -> x
                      otherwise -> 0
Run Code Online (Sandbox Code Playgroud)

但这很有效

third :: Integral a => [a] -> a
third xs = case xs of 
                      [] -> 0
                      (_:_:x:_) -> x
                      otherwise -> 0
Run Code Online (Sandbox Code Playgroud)

sep*_*p2k 5

列表模式[p1, ..., pn]匹配,其中每个元素的图案相匹配的n元素列表p1通过pn分别。该模式[p]是一个只有一个元素的列表模式,因此它匹配一个列表,其中恰好有一个与模式匹配的元素p。所以[_:_:x:_]匹配一个只包含一个元素的列表,该元素必须是一个匹配模式的列表_:_:x:_

那么为什么相同的逻辑不适用于(p)和 元组?也就是说,为什么不(_:_:x:_)匹配包含列表的单元素元组?因为没有单元素元组这样的东西。Haskell 中的括号在某种程度上是重载的:当它们包含逗号时,它们表示一个元组;如果它们不包含 ( ()),则表示单位值;否则它们只是用于分组。

所以模式(_:_:x:_)只是匹配模式_:_:x:_。括号通常只是用来避免歧义(f x:y = ...将被解释为(f x):y = ...,不是f (x:y) =...),但在这种情况下,它们实际上是多余的。你可以写:

third xs = case xs of 
                      [] -> 0
                      _:_:x:_ -> x
                      otherwise -> 0
Run Code Online (Sandbox Code Playgroud)


mb1*_*b14 5

实际上有办法写一个清单

[1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

要么

1:2:3:[]
Run Code Online (Sandbox Code Playgroud)

(注意:[]最后).第一种是编写列表的传统方式,但实际上只是编写第二种方法的捷径.:表示cons运算符并[]表示一个空列表(看起来与[] in the first version).3:[] means , take 3 and prepend it to the empty list (which is then equivalent to [3]).2:3:[]相同means : prepend 2 to the previous list (which is also equivalent to 2:[3].最后1:2:3:[]相当于1:[2,3].所以

[1, 2, 3]
1:[2,3]
1:2:[3]
1:2:3:[]
Run Code Online (Sandbox Code Playgroud)

是等价的.但是 [1:2:3:[]]相当于[[1,2,3]]没有[1,2,3].

所以,当你进行模式匹配时(x:_),你会说:我想要一个以列表开头的列表x,我不关心它的尾部(因此它可以是任何长度).当你写作时[x:_],你实际上正在写作[(x:_)],这意味着,我想要一个ONE元素的列表,这个元素以x.这可能是正确的,但是您匹配模式的列表不是a的列表,而是a([[a]])列表的列表,它与您的类型签名不匹配.