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

时间:2018-04-14 12:14:50

标签: haskell

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

例如 - 下面不起作用

third :: Integral a => [a] -> a
third xs = case xs of 
                      [] -> 0
                      [_:_:x:_] -> x
                      otherwise -> 0

但这有效

third :: Integral a => [a] -> a
third xs = case xs of 
                      [] -> 0
                      (_:_:x:_) -> x
                      otherwise -> 0

2 个答案:

答案 0 :(得分:5)

实际上有办法写一个清单

[1, 2, 3]

或者

1:2:3:[]

(注意最后的:[])。第一种是编写列表的传统方式,但实际上只是编写第二种方法的捷径。 :表示cons运算符,[]表示空列表(看起来与[] in the first version). 3相同:[] means , take 3 and prepend it to the empty list (which is then equivalent to [3]). 2:3:[] { {1}}。最后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:[] 相当于[1:2:3:[]]而不是[[1,2,3]]

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

答案 1 :(得分:4)

列表模式[p1, ..., pn]匹配n元素列表,其中每个元素分别与模式p1pn匹配。模式[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