我是初学者,基本上我需要对此进行解释
他用这个代码回答:
tupleToList :: [(a,a)] -> [a]
tupleToList ((a,b):xs) = a : b : tupleToList xs
tupleToList _ = []
但我不明白他为什么不使用:
tupleToList [] = []
tupleToList ((a,b):xs) = a : b : tupleToList xs
就像我通常在指南的第一个练习中看到的那样。 我知道"_"是什么,但是,当列表为空时,使用"[]"不是更好吗?
就像我通常在指南的第一个练习中看到的那样。我知道
_
是什么,但是,当列表为空时,使用[]
不是更好吗?
在语义上,两者是相同的,因为一个2元组只有一个构造函数(a,b)
,而一个列表有两个构造函数[]
和(h:t)
。
由于唯一与第一个子句不匹配的模式是空列表,因此通配符_
等效于[]
。
由于[]
和((a,b):xs)
是析取模式(即没有值可以匹配两种模式(,因此当显式使用[]
时,两种模式的顺序并不重要。然后,我们可以按照我们喜欢的任何顺序编写它。
一些Haskell程序员更喜欢使用显式模式(所以使用[]
而不是_
(,因为这意味着我们知道我们实际使用该子句处理哪些值。如果以后Haskell社区决定引入一个额外的列表构造函数(是的,对于列表来说,这不太可能,但对于其他data
类型,这可能更合理(,Haskell编译器可以(-Wincomplete-patterns
(给出警告,指出某些模式没有被覆盖。通配符当然涵盖了所有模式,但也许右侧的表达式不是我们为附加构造函数准备的表达式。
因此,我建议仅在您想通过同一子句匹配多个模式时才使用通配符。如果清楚其他模式是什么,最好明确。就像Python的Zen所说(是的,它是Python,但大多数概念在某种程度上是通用的(:">显式比隐式更好"。
没有区别:它们的语义完全相同。
tupleToList [] = []
tupleToList ((a,b):xs) = a : b : tupleToList xs
相当于
tupleToList ((a,b):xs) = a : b : tupleToList xs
tupleToList [] = []
相当于
tupleToList ((a,b):xs) = a : b : tupleToList xs
tupleToList _ = []
通常,当我们需要模式匹配多个情况时,会使用通配符_
。 例如
myAnd :: Bool -> Bool -> Bool
myAnd True y = y
myAnd False _ = False
上面,我们可以分别枚举False False
和False True
情况,并使用三个方程,但使用通配符更方便(并且使我们的函数稍微懒惰,例如myAnd False undefined
计算结果为False
(。
最后,这主要是风格问题。通常,当通配符_
只能代表一种情况时,最好将其拼写出来,明确说明。这样,代码通常更具可读性。例如
not :: Bool -> Bool
not False = True
not _ = False
等效但比
not :: Bool -> Bool
not False = True
not True = False
当然,case
表达也是如此。
case x of
Just y -> 1 + y
Nothing -> 0
可以说比
case x of
Just y -> 1 + y
_ -> 0