确定列表是否以字母“ a”开头的函数的定义如下:
test :: [Char] -> Bool
test ['a',_] = True
test _ = False
或
test :: [Char] -> Bool
test ('a':_) = True
test _ = False
为什么第一个使用[]
,而第二个使用()
?
第二个是否使用('a':_)
表示元组或列表?
test
的参数是否具有列表类型[Char]
?()
不能代表一个元组,它怎么能代表一个列表?答案 0 :(得分:6)
第二个是否使用
('a':_)
表示元组或列表?
一个列表。
如果是列表,
()
不能代表一个元组,它怎么能代表一个列表?
否,这是unit type [wiki]。它不是元组,也不是列表。有时,如Wikipedia文章所述,它被解释为0元组。它也在GHC.Tuple
中定义。
为什么第一个使用
[]
,而第二个使用()
?
两者是不等效的。前者将一个完全匹配 两个元素的列表匹配,其中第一个元素是'a'
,而后者则匹配一个具有至少一个元素的列表,其中第一个元素元素是'a'
。但是后者可以匹配具有一个元素,三个元素等的列表,而前者只能匹配具有恰好两个元素的列表。
(:)
是列表的数据构造器。确实:
Prelude> :i (:)
data [] a = ... | a : [a] -- Defined in ‘GHC.Types’
infixr 5 :
('a': _)
只是((:) 'a' _)
的一种更好形式。因此,我们在这里使用列表数据构造函数之一。
['a', _]
是(:) 'a' ((:) _ [])
的语法糖,因此这里我们匹配一个以'a'
开头的列表,而尾部是一个列表,其头部为一个值,我们不在乎关于它的尾部为空列表数据构造函数。
答案 1 :(得分:5)
Haskell的列表符号只是用于将元素“限制”在空列表上(即使用:
运算符)的语法糖。
换句话说,
[x,y,z]
是...的语法糖
x:(y:(z:[]))
(尽管通常将这种形式写成x:y:z:[]
,但不带括号,因为:
是右相关的)。
因此,在您引用的示例中,('a':_)
代表第一个元素为'a'
的任何列表,而['a',_]
是(a:(_:[]))
的糖,它是长度精确的列表2,其第一个元素为a
。
请注意,元组完全是另外一些东西,用括号中的一系列值(用逗号分隔)表示。
答案 2 :(得分:1)
在Haskell中,数据构造器是符号,一些示例可能会使您感到困惑:
() :: ()
类型为unit
,其构造函数为()
,其值为()
然后有:
(,) :: a -> b -> (a,b)
(,)
是元组的构造函数,例如(1,"b")
可以是(1,) “b”
或(,) 1 “b”
最后您的案子:
(:) :: a -> [a] -> [a]
例如1:[]
可以是[1]
或(:) 1 []