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

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

Haskellinsert定义的两个版本,一个使用方括号,另一个使用括号:

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

的第二个定义insert'不起作用的原因是什么?

它给出的错误消息,对于任何想知道的人:

test.hs:3:12: error:
    • Couldn't match expected type ‘Int’ with actual type ‘[Int]’
    • In the pattern: x : xs
      In the pattern: [x : xs]
      In an equation for ‘insert'’:
          insert' y [x : xs]
            | y <= x = y : x : xs
            | otherwise = x : insert' y xs
  |
3 | insert' y [x:xs] | y <= x = y:x:xs | otherwise = x : insert' y xs
  |  

回答

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

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]只能匹配元素为列表的列表。


回答

(x:xs)因为模式将匹配任何非空列表x及其头部和xs尾部。

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

这就是为什么您的第二个定义暗示第二个参数的类型是[[a]],但您已将其声明为[Int]。并且Int无法匹配[a]。(这a也被确定为 an Int,因为您比较了xand y,并且y第一个参数被声明为 an Int,但这不会改变任何东西)。

     [ [a] ]
     [ Int ]
 ----------------
  ***mismatch***

  • It might be worth explicitly pointing out that there's no syntactic "magic" behind the parentheses in `(x:xs)`, and that they're only used because of precedence (`insert y x:xs` would be parsed as `(insert y x) : xs`)

以上是关于列表,方括号和圆括号有什么区别?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>