为什么list++需要扫描list左边的所有元素?
Why list ++ requires to scan all elements of list on its left?
Haskell教程说,当我们使用"Hello"++"World"时要小心,新的列表构造必须访问所有单个元素(这里,[=16的每个字符=]), 所以如果"++"左边的列表很长,那么使用"++"会降低性能。
我想我没有理解正确,难道Haskell的开发者从不调整列表操作的性能吗?为什么此操作仍然很慢,以便在任何 lambda 函数或柯里化中具有某种语法一致性?
有什么提示吗?谢谢。
如果你有一个不可变的列表,它有一个头部和一个对尾部的引用,你不能改变它的尾部。如果要向列表的 'end' 添加一些内容,则必须到达末尾,然后将所有项目一一添加到右侧列表的头部。它是不可变列表的基础属性:连接很昂贵。
Haskell 列表就像单链表:它们要么是空的,要么由一个头和一个(可能是空的)尾组成。因此,在将某些内容附加到列表时,您首先必须遍历整个列表才能到达末尾。所以你最终遍历了整个列表(即你追加的列表),这需要 O(n) 运行时间。
在某些语言中,"list" 是一种通用序列类型,旨在为连接、拆分等提供良好的性能。在 Haskell 和大多数传统函数式语言中,列表是一种非常具体的数据结构,即单链表。如果你想要一个通用的序列类型,你应该使用 containers
包中的 Data.Sequence
(它已经安装在你的系统上并且为各种操作提供了非常好的大 O 渐近),或者可能是其他一些针对常见使用模式进行了更深入优化的。
Haskell教程说,当我们使用"Hello"++"World"时要小心,新的列表构造必须访问所有单个元素(这里,[=16的每个字符=]), 所以如果"++"左边的列表很长,那么使用"++"会降低性能。
我想我没有理解正确,难道Haskell的开发者从不调整列表操作的性能吗?为什么此操作仍然很慢,以便在任何 lambda 函数或柯里化中具有某种语法一致性?
有什么提示吗?谢谢。
如果你有一个不可变的列表,它有一个头部和一个对尾部的引用,你不能改变它的尾部。如果要向列表的 'end' 添加一些内容,则必须到达末尾,然后将所有项目一一添加到右侧列表的头部。它是不可变列表的基础属性:连接很昂贵。
Haskell 列表就像单链表:它们要么是空的,要么由一个头和一个(可能是空的)尾组成。因此,在将某些内容附加到列表时,您首先必须遍历整个列表才能到达末尾。所以你最终遍历了整个列表(即你追加的列表),这需要 O(n) 运行时间。
在某些语言中,"list" 是一种通用序列类型,旨在为连接、拆分等提供良好的性能。在 Haskell 和大多数传统函数式语言中,列表是一种非常具体的数据结构,即单链表。如果你想要一个通用的序列类型,你应该使用 containers
包中的 Data.Sequence
(它已经安装在你的系统上并且为各种操作提供了非常好的大 O 渐近),或者可能是其他一些针对常见使用模式进行了更深入优化的。