List 列表构造/连接的语法

List 列表构造/连接的语法,list,haskell,syntax,List,Haskell,Syntax,我在Haskell只呆了两天,想知道下面两个函数定义之间的区别是什么: Prelude> let swap (x1:x2:xs) = x2:x1:xs Prelude> swap [1..5] [2,1,3,4,5] Prelude> let swap' (x1:x2:xs) = [x2] ++ [x1] ++ xs Prelude> swap' [1..5] [2,1,3,4,5] 也就是说,是什么使x2:x1:xs不同于[x2]+[x1]++xs? 请和谢谢。类型签

我在Haskell只呆了两天,想知道下面两个函数定义之间的区别是什么:

Prelude> let swap (x1:x2:xs) = x2:x1:xs
Prelude> swap [1..5]
[2,1,3,4,5]
Prelude> let swap' (x1:x2:xs) = [x2] ++ [x1] ++ xs
Prelude> swap' [1..5]
[2,1,3,4,5]
也就是说,是什么使x2:x1:xs不同于[x2]+[x1]++xs?
请和谢谢。

类型签名是一个很好的开始:

(:) :: a -> [a] -> [a]
(++) :: [a] -> [a] -> [a]
您可以通过ghci中的
:type(:)
:type(++)
找到这些

正如您可以从类型签名中看到的,这两种签名都用于生成列表

操作符用于构造列表(并将它们再次拆分以进行模式匹配)。要创建一个列表,只需使用
1:2:3:[]
构建它。
的第一个元素是要添加到列表前面的项目,第二个元素是列表(也由
或由
[]
表示的空列表组成)


++
运算符是列表连接。它需要两个列表并将它们附加在一起<代码>[1,2,3]++[4,5,6]是合法的,而
1++[1,2,3]
不是。

这与语法无关。(:)和(++)只是不同的运算符。(:)是从一个元素和另一个列表构造列表的构造函数。(++)生成一个新列表,该列表是两个列表的串联。因为(++)不是构造函数,所以不能在模式中使用它

现在我们来讨论语法:符号

[x2]
你用的是一个缩写

x2:[]
因此,您在第二个示例中真正做到的是:

(x2:[]) ++ (x1:[]) ++ xs

因此,在构建列表时,您无法避免(:),这是最终实现它的唯一方法。请注意,您必须构造中间列表才能使用(++)。

不同的意思是什么?它们的含义是一样的,即swap和swap做同一件事。这一点越来越清楚了。对于上面的一个,我从一个列表中创建了一个列表,而对于下面的一个,我创建了3个列表,并将它们重新连接在一起。这是否意味着最上面的一个会更快/更高效?在最上面的一个中,您通过交换的前两个元素和相同的尾部创建列表。在第二个列表中,您通过将前两个分开,然后将它们构建到列表中,并用尾部连接它们来创建列表。我想第一个会更有效率,但我不认为这是最重要的。在我看来,第一个是比较地道的Haskell,所以你应该选择它。谢谢!经过这里的解释和今天更多的研究,这一切都更有意义。