`('a':_)`代表一个元组还是一个列表?

时间:2019-07-27 13:20:47

标签: list haskell

确定列表是否以字母“ a”开头的函数的定义如下:

test :: [Char] -> Bool 
test ['a',_] = True  
test _ = False

test :: [Char] -> Bool 
test ('a':_) = True  
test _ = False

为什么第一个使用[],而第二个使用()

第二个是否使用('a':_)表示元组或列表?

  • 如果是元组,test的参数是否具有列表类型[Char]
  • 如果是列表,()不能代表一个元组,它怎么能代表一个列表?

3 个答案:

答案 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 []