【问题标题】:Why is Haskell's default string implementation a linked list of chars?为什么 Haskell 的默认字符串实现是一个字符的链表?
【发布时间】:2012-12-01 16:07:30
【问题描述】:

众所周知,Haskell 的默认 String 实现在速度和内存方面效率不高。据我所知,[] lists 通常在 Haskell 中作为单链表实现,对于大多数小型/简单数据类型(例如Int),这似乎不是一个好主意,但对于String这似乎完全是矫枉过正。关于此事的一些意见包括:

Real World Haskell

在像这样的简单基准测试中,即使是用 Python 等解释性语言编写的程序也能胜过使用 String 的 Haskell 代码一个数量级。

Efficient String Implementation in Haskell

由于String只是[Char],即Char的链表,这意味着String的引用局部性较差,再次意味着String在内存中相当大,至少为N *(21bits + Mbits ) 其中 N 是字符串的长度,M 是指针的大小 (...)。字符串不太可能被编译器优化为循环等。

我知道 Haskell 有 ByteStrings(和 Arrays)有几种不错的风格,它们可以很好地完成这项工作,但我希望默认实现是最有效的实现。

TL;DR: 为什么 Haskell 的默认 String 实现是一个单链表,即使它效率极低并且很少用于现实世界的应用程序(除了非常简单的应用程序)?有历史原因吗?是不是更容易实现?

【问题讨论】:

  • 我认为这是因为[Char] 非常舒适。
  • 我觉得值得一提的是,ByteString 绝对不是文本类型,Array 也好不了多少——Text 确实是正确的解决方案。
  • Haskell /= GHC。在 Haskell 的早期,当有几个不同的编译器/解释器时,有一个“一路乌龟”的字符串表示是一个值得称道的设计。
  • 就我个人而言,我希望默认实现是简单的、有意义的懒惰、如果天真地使用时行为正确,并且对于简单的使用来说“足够快”。 [Char] 在这方面做得很好,而 ByteString 强调不行。
  • 我想知道人们是否也抱怨在其他语言中存在StringBuilder 类,默认字符串实现对于重复连接非常低效......

标签: string performance haskell linked-list


【解决方案1】:

为什么 Haskell 的默认 String 实现是单链表

因为单链表支持:

  • 通过模式匹配进行归纳
  • 具有有用的属性,例如 Monad、Functor
  • 具有适当的参数多态性
  • 天生懒惰

所以String[Char](unicode 点)表示符合语言目标的字符串类型(截至 1990 年),并且基本上是“免费”与列表库一起提供的。

总而言之,从历史上看,语言设计者对设计良好的核心数据类型更感兴趣,而不是文本处理的现代问题,所以我们有一个优雅、易于理解、易于教授的 String 类型,即' t 完全是 unicode 文本块,不是密集、打包、严格的数据类型。

【讨论】:

  • 所有答案都为我提供了新的有价值的信息,但你的最完整(这似乎是你所有答案的共同特征:))。
  • 这些都是非常好的属性。它们是人们使用 Haskell 而不是其他语言的一些关键原因。令人惊讶的是,有替代的字符串实现放弃了这些。为什么编译器不能有效地实现 [Char]?对此的某种通用解决方案可以使各种事情变得更加高效。
  • @PaulHarrison:一方面,其他人不那么懒惰,编译器不会让事情变得更严格,除非可以确定这样做不会改变程序的行为。一般来说,这不是一件容易的事。
【解决方案2】:

效率只是衡量抽象的一个轴。虽然列表对于 text-y 操作非常低效,但它们非常方便,因为有许多以多态方式实现的列表操作在专用于 [Char] 时具有有用的解释,因此您在库实现和用户的大脑。

目前尚不清楚,如果以我们目前的经验水平从头开始设计语言,是否会做出相同的决定;但是,在获得经验之前并不总是可以完美地做出决定。

【讨论】:

  • 相当多的 text-y 操作在概念上是对最多遍历字符串一次的 unicode 字符序列的操作。一个“高效”的文本类型不是一次强制大量数据进入内存,而不是一次只强制几个(:)。使用[Char] 的问题并不像有时描述的那样具有灾难性。
【解决方案3】:

在这一点上,这可能是历史性的:使ByteString 如此高效的优化是最近,而[Char] 比它们早了很多年。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-28
    • 1970-01-01
    • 2020-01-10
    • 1970-01-01
    相关资源
    最近更新 更多