Data.Text与字符串


78

尽管Haskell社区的普遍观点似乎是总是使用Text代替总是更好String,但是大多数可维护库的API仍然是面向的这一事实使String我感到困惑。另一方面,有一些值得注意的项目,这些项目将全部视为String错误,并且提供了Prelude-String面向功能的所有实例都替换为Text-counterparts的实例。

因此,String除了向后兼容和标准的Prelude兼容以及“切换机制”之外,人们是否有理由继续编写面向对象的API?与之Text相比,是否还有其他缺点String

特别是,我对此很感兴趣,因为我正在设计一个库并试图决定使用哪种类型来表达错误消息。


支持这两者有多困难?
Daniel Wagner

6
@Vektorweg我会争辩。由于String只是Chars列表的别名,因此自然具有与整体数据不同的性能特征Text。两种类型都不是编译器关心的问题,因为它们不是原始的,而是在库中定义的。
Nikita Volkov

1
@DanielWagner难道不是动机不足吗?无论如何,问题在于通用方法,如果在整个库中存在一种支持两种类型的共享模式,那将是相当大的。
Nikita Volkov

3
@Vektorweg上有一篇很好的博客文章,关于Sufficiently Smart Compiler。(我刚刚意识到它也提到了GHC。)
kqr

1
去文本!如果我们停止添加依赖于字符串的代码,那么后代有一天可能会受益于无字符串的世界。
Titou

Answers:


30

我无条件的猜测是,大多数库作者都不想添加比必要更多的依赖项。由于字符串实际上是每个Haskell发行版的一部分(它是语言标准的一部分!),如果您使用字符串并且不要求您的用户从黑名单中整理出Text发行版,那么采用起来就容易得多。

这是您必须忍受的那些“设计错误”之一,除非您可以说服大多数社区过夜。只要看看使Applicative成为Monad的超类花了多长时间(一个相对较小但急切需要的更改),并想象用Text替换所有String东西将花费多长时间。


要回答您的更具体的问题:除非您通过使用Text获得明显的性能优势,否则我会选择String。错误消息通常是很小的一次性事件,因此使用String并不是什么大问题。

另一方面,如果您是那种避免实用主义追求理想主义的思想纯粹主义者,那么请选择文本。


*我将设计错误放在吓人的引号中,因为字符串作为字符列表是一个简洁的属性,使它们易于推理并与其他现有的列表操作函数集成。


4
这并不是某种狂热的纯洁,只是我宁愿做出更好的转换(如果确实如此),而不是停滞于次佳的方法。好的,您确认使用Text本质上没有缺点吗?
Nikita Volkov

4
@NikitaVolkov如果您想为转换做出贡献,我认为您可以通过参与更新标准以及游说/转换现有库的过程来做出更大的改变。除了您可以想到的缺点之外,几乎没有其他缺点,例如采用率和希望在第一个字母上进行模式匹配或使用Data.List中的map的人员,等等。
kqr

6
这可能不再那么重要了,因为Data.Text在今天已经很常见了,并且随GHC开箱即用(我认为这些天大多数人都在使用)。
Profpatsch 2014年

23

如果您的API旨在处理大量面向字符的数据和/或各种编码,则您的API应该使用Text

如果您的API主要用于处理小的一次性字符串,则可以使用内置的String类型。

对大量文本使用字符串将使使用您的API的应用程序消耗大量内存。将其与外部编码一起使用可能会严重复杂化用法,具体取决于您API的工作方式。

字符串非常昂贵(至少5N个单词,其中N是字符串中Char的数量)。一个字的位数与处理器体系结构的位数相同(例如32位或64位):http : //blog.johantibell.com/2011/06/memory-footprints-of-some-common-data.html


11
我认为ASCII与它没有任何关系:字符串和文本均同样支持Unicode,从而将实际编码推到了抽象级别之下。在这两种情况下,您都只需要在程序边界上担心它。Unicode支持不是在两者之间进行选择的好标准。
Tikhon Jelvis

4
你混了StringByteString关于ASCII。
Nikita Volkov

1
@TikhonJelvis是否存在Char字符串中的字符只能是Unicode字符的一部分而不是单个Unicode字符的问题?那不会引起混乱吗?Data.Text是否可以解决此问题?
若昂·波特拉

3
@JoãoPortela:HaskellChar与Java或C#不同char。它们是完整的Unicode代码点(32位)。
Tobias Brandt 2014年

1
他们是32位吗?我一直以为它们是16位的。感谢您清理。
若昂里斯本

9

在小型项目中至少有三个原因使用[Char]。

  1. [Char] 不依赖任何奥秘的人员,例如外来指针,原始内存,原始数组等,它们在不同平台上的工作方式可能不同,甚至完全不可用

  2. [Char]是Haskell中的lingua franka。至少有三个“高效率”的方式在Haskell处理Unicode数据:utf8-bytestringData.Text.Text并且Data.Vector.Unboxed.Vector Char,每个都需要处理额外的软件包。

  3. 通过使用[Char]一个命令可以访问[]monad的所有功能,包括许多特定功能(替代字符串程序包确实会尝试提供帮助),但仍然可以

就个人而言,我认为基于utf16Data.Text问题是haskell社区中最令人质疑的问题之一,因为utf16结合了utf8utf32编码的缺陷,却没有任何好处。


1
您能否提供更多有关为什么您认为utf16较差的信息?不一定是该答案的一部分,但可能是一篇详述您的立场的文章。
Wizek '16

2
@Wizek-这是一个合理的普遍看法。请参阅programmers.stackexchange.com/questions/102205/…
Jules

5

我想知道Data.Text是否总是比Data.String更有效吗???

例如,“ cons”对于字符串是O(1),对于文本是O(n)。字符串的附加值为O(n),严格文本的附加值为O(n + m)。同样

    let foo = "foo" ++ bigchunk
        bar = "bar" ++ bigchunk

与严格的文本相比,字符串的空间使用效率更高。

与效率无关的其他问题是模式匹配(透明代码)和延迟(在字符串中每个字符可预测,在某种程度上取决于延迟文本中的实现)。

文本显然对于静态字符序列和就地修改非常有用。对于其他形式的结构编辑,Data.String可能具有优势。


1
性能和效率不只是大问题而已。字符串实现是一个链表,每个单个字符都有一个节点。对于一个简单的字符串,这会增加很多内存,缓存和碎片。
贾斯汀·迈纳斯

4

我认为String保留的唯一技术原因不是。而且我可以看到几个解决方案。

总的来说,我首先认为在Text / String案例中只有一个最佳解决方案:

  • 弦乐表演很差,每个人都同意

  • 文字不难使用。字符串上常用的所有功能都可以在文本上使用,另外一些在字符串上下文中有用的功能(替换,填充,编码)

  • 除非所有基本函数都变为多态的,否则具有两个解决方案会产生不必要的复杂性。证明:关于自动转换有一些疑问。所以这一个问题。

因此,一种解决方案不如两种解决方案复杂,而String的缺点将使其最终消失。越早越好!


1
并不是那么简单,不。那里有很多非平凡的字符串处理代码,它们都是围绕着设计的String,因此根本无法正常工作Text
dfeuer

@dfeuer我将对指针非常感兴趣-在这些情况下,我非常缺乏第一手经验。
Titou
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.