在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
答案 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元素列表,其中每个元素分别与模式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