List 将元素添加到列表末尾的正确方法?

List 将元素添加到列表末尾的正确方法?,list,haskell,List,Haskell,我在Haskell页面上读到关于在列表的末尾添加元素的内容 用这个例子,我自己尝试了一下。考虑到下面的列表,我想在其末尾添加编号56 例如: let numbers = [4,8,15,16,23,42] numbers ++ [56] 我被下面的评论吓坏了: 将项目添加到列表的末尾是一个很好的练习,但通常 你不应该在真正的Haskell程序中这样做。它很贵,而且 表示您正在以错误的顺序生成列表。有 通常是更好的方法 ,我意识到我实际上在做的是创建一个列表,其中56是唯一的元素,我将它与数字

我在Haskell页面上读到关于在
列表的末尾添加元素的内容

用这个例子,我自己尝试了一下。考虑到下面的
列表
,我想在其末尾添加编号
56

例如:

let numbers = [4,8,15,16,23,42] 
numbers ++ [56]
我被下面的评论吓坏了:

将项目添加到列表的末尾是一个很好的练习,但通常 你不应该在真正的Haskell程序中这样做。它很贵,而且 表示您正在以错误的顺序生成列表。有 通常是更好的方法

,我意识到我实际上在做的是创建一个
列表
,其中
56
是唯一的元素,我将它与
数字
列表
相结合。对吗


使用
++
是将元素添加到
列表末尾的正确方法吗?

这是正确的方法,因为所有这样做的方法都必须减少至少那么多的工作量。问题是根本不想在列表的末尾追加内容。对于不可变的链表来说,这不是一个有效的操作


更好的方法是找出如何在不这样做的情况下解决您的特定问题。有很多潜在的方法。选择正确的一个取决于你所做的细节。也许你可以正确地利用懒惰来逃避惩罚。也许你最好向后生成列表,然后在最后反转一次。也许您最好使用不同的数据结构。这完全取决于您的特定用例

++[x]
是将元素添加到列表末尾的正确方法,但注释的意思是不应将元素添加到列表末尾

由于列表的定义方式,在末尾添加元素始终需要制作列表的副本。就是

xs ++ ys
需要复制所有的
xs
,但可以重复使用
ys
不变

如果
xs
只是一个元素(即,我们将添加到列表的开头),那就没有问题:复制一个元素几乎不需要任何时间

但是如果
xs
更长,我们需要在
++
上花费更多的时间

如果我们重复这样做(即,我们通过不断在末尾添加元素来建立一个大列表),那么我们需要花费大量时间制作冗余副本。(以这种方式构建n元素列表是一个O(n2)操作。)


如果需要这样做,通常有更好的方法来构造算法。例如,您可以按相反的顺序构建列表(在开始时添加元素),并且只在末尾调用
reverse

您熟悉
[a]
的定义吗?这是一个嵌套的结构,就像一个俄罗斯娃娃:列表的“结尾”最好被认为是中心。如果你想添加一个新的最小的玩偶,你需要打开每一层(O(n)操作)。试着为自己实现
++
“这很昂贵,并且表明您正在以错误的顺序构建列表。通常有更好的方法”这一部分非常重要。也许你应该专注于如何以相反的顺序创建你的
numbers
列表,然后像
56:numbers
那样提高效率。