Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/jsf/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 关于列表,方括号和圆括号有什么区别?_Haskell_Recursion_Types_Pattern Matching_Type Mismatch - Fatal编程技术网

Haskell 关于列表,方括号和圆括号有什么区别?

Haskell 关于列表,方括号和圆括号有什么区别?,haskell,recursion,types,pattern-matching,type-mismatch,Haskell,Recursion,Types,Pattern Matching,Type Mismatch,正如标题所暗示的,我不确定方括号和圆括号在列表方面的区别 Haskell的插入定义了两个版本,一个使用方括号,另一个使用括号: insert' :: Int -> [Int] -> [Int] insert' y [] = [y] insert' y (x:xs) | y <= x = y:x:xs | otherwise = x : insert' y xs ---- insert' y [x:xs] | y <= x = y:x:xs | otherwise = x

正如标题所暗示的,我不确定方括号和圆括号在列表方面的区别

Haskell的
插入定义了两个版本,一个使用方括号,另一个使用括号:

insert' :: Int -> [Int] -> [Int]
insert' y [] = [y]
insert' y (x:xs) | y <= x = y:x:xs | otherwise = x : insert' y xs
----
insert' y [x:xs] | y <= x = y:x:xs | otherwise = x : insert' y xs
(x:xs)
作为一种模式,任何非空列表都将与
x
头和
xs
尾匹配

[x:xs]
作为一个模式,它将匹配一个单例列表——一个只包含一项的列表——这是一个非空列表,与模式
(x:xs)
匹配。模式
[x:xs]
实际上相当于模式
[(x:xs)]
。这是一种嵌套模式,Haskell允许这样做。外部模式匹配单例列表,内部模式匹配非空列表。此位置的括号是可选的

这就是为什么您的第二个定义暗示第二个参数的类型是
[[a]]
,但您已经声明它是
[Int]
。和
Int
不能匹配
[a]
。(由于比较
x
y
,并且
y
第一个参数声明为
Int
,因此
a
也被确定为
Int
,但这不会改变任何事情)

(x:xs)
作为一种模式,任何非空列表都将与
x
头和
xs
尾匹配

[x:xs]
作为一个模式,它将匹配一个单例列表——一个只包含一项的列表——这是一个非空列表,与模式
(x:xs)
匹配。模式
[x:xs]
实际上相当于模式
[(x:xs)]
。这是一种嵌套模式,Haskell允许这样做。外部模式匹配单例列表,内部模式匹配非空列表。此位置的括号是可选的

这就是为什么您的第二个定义暗示第二个参数的类型是
[[a]]
,但您已经声明它是
[Int]
。和
Int
不能匹配
[a]
。(由于比较
x
y
,并且
y
第一个参数声明为
Int
,因此
a
也被确定为
Int
,但这不会改变任何事情)


与几乎所有其他语言一样,Haskell中的括号实际上没有任何作用。它们帮助解析器知道要将哪些内容组合在一起,就是这样;它们不会改变它们内部事物的含义,如果解析器能够神奇地猜出您打算在每个选择点对事物进行分组的方式,那么我们根本不需要它们。因此,所有这些模式的行为都完全相同:

x
(x)
((x))
(((((((((x)))))))))
x:xs
(x:xs)
((x:xs))
(((((((((x:xs)))))))))
所有这些模式也完全相同:

x
(x)
((x))
(((((((((x)))))))))
x:xs
(x:xs)
((x:xs))
(((((((((x:xs)))))))))
有时我们必须使用后面的一个,比如
(x:xs)
,而不是第一个--
x:xs
,来通知解析器我们打算将这些东西分组在一起。但是括号不会改变模式的含义

另一方面,方括号用于构造列表。它们具有实际的运行时含义:它们在内存中分配一个新的数据结构并对其进行初始化。例如,
3
是一个数字,但
[3]
是一个包含单个元素的列表,
[3,4]
是一个包含两个元素的列表,
[[3]]
是一个列表列表,依此类推。同样的行为也适用于模式:

x -- match anything (even a list!) and bind x to its value
[x] -- match a list with a single element, and bind x to that element's value
[x,y] -- match a list with two elements, and bind x and y to those elements' values
[[x]] -- match a nested list; the outer and inner lists both have one element; bind x to the first element's first element
现在我们可以讨论您的具体示例。模式
x:xs
是一种模式,它将任何列表与至少一个元素相匹配,将
x
绑定到第一个元素,并将
xs
绑定到列表的其余部分。模式
(x:xs)
的作用完全相同。另一方面,模式
[x:xs]
,恰好与一个元素的列表相匹配,因为有方括号;然后,该列表的唯一元素与模式
x:xs
匹配,行为如上所述


这样做的一个结果是,
x:xs
可以将列表与任何类型的元素匹配——比如,
Int
——但是
[x:xs]
只能匹配元素为列表的列表。

与几乎所有其他语言一样,Haskell中的括号实际上没有任何作用。它们帮助解析器知道要将哪些内容组合在一起,就是这样;它们不会改变它们内部事物的含义,如果解析器能够神奇地猜出您打算在每个选择点对事物进行分组的方式,那么我们根本不需要它们。因此,所有这些模式的行为都完全相同:

x
(x)
((x))
(((((((((x)))))))))
x:xs
(x:xs)
((x:xs))
(((((((((x:xs)))))))))
所有这些模式也完全相同:

x
(x)
((x))
(((((((((x)))))))))
x:xs
(x:xs)
((x:xs))
(((((((((x:xs)))))))))
有时我们必须使用后面的一个,比如
(x:xs)
,而不是第一个--
x:xs
,来通知解析器我们打算将这些东西分组在一起。但是括号不会改变模式的含义

另一方面,方括号用于构造列表。它们具有实际的运行时含义:它们在内存中分配一个新的数据结构并对其进行初始化。例如,
3
是一个数字,但
[3]
是一个包含单个元素的列表,
[3,4]
是一个包含两个元素的列表,
[[3]]
是一个列表列表,依此类推。同样的行为也适用于模式:

x -- match anything (even a list!) and bind x to its value
[x] -- match a list with a single element, and bind x to that element's value
[x,y] -- match a list with two elements, and bind x and y to those elements' values
[[x]] -- match a nested list; the outer and inner lists both have one element; bind x to the first element's first element
现在我们可以讨论您的具体示例。模式
x:xs
是一种模式,它将任何列表与至少一个元素相匹配,将
x
绑定到第一个元素,并将
xs
绑定到列表的其余部分。模式
(x:xs)
的作用完全相同。另一方面,模式
[x:xs]
,恰好与一个元素的列表相匹配,因为有方括号;然后,该列表的唯一元素与模式
x:xs
匹配,行为如上所述

一个