文字或字节串


78

美好的一天。

我现在讨厌Haskell的一件事是使用字符串的软件包数量众多。

首先,我使用了原生的Haskell[Char]字符串,但是当我尝试开始使用hackage库时,却在无尽的转换中完全迷失了。每个包似乎都使用不同的字符串实现,有些则采用他们自己的手工东西。

接下来,我选择了使用Data.Text字符串和OverloadedStrings扩展名重写代码,Text因为它具有更广泛的功能集,但是似乎很多项目都更喜欢ByteString
有人可以简短地说明为什么要使用其中一个?

PS:顺便说一句如何从转换TextByteString

无法将预期的类型Data.ByteString.Lazy.Internal.ByteString 与推断的类型Text匹配 预期的类型:IO Data.ByteString.Lazy.Internal.ByteString推断的类型:IO文本

我试图encodeUtf8Data.Text.Encoding,但没有运气:

无法将预期的类型 Data.ByteString.Lazy.Internal.ByteString 与推断的类型Data.ByteString.Internal.ByteString进行匹配

UPD:

感谢您的答复,*大块头的好处看起来很像,但结果令我有些震惊,我的原始功能看起来像这样:

htmlToItems :: Text -> [Item]
htmlToItems =
    getItems . parseTags . convertFuzzy Discard "CP1251" "UTF8"

现在变成:

htmlToItems :: Text -> [Item]
htmlToItems =
    getItems . parseTags . fromLazyBS . convertFuzzy Discard "CP1251" "UTF8" . toLazyBS
    where
      toLazyBS t = fromChunks [encodeUtf8 t]
      fromLazyBS t = decodeUtf8 $ intercalate "" $ toChunks t

是的,此函数不起作用是因为它的错误,如果我们提供Text给它,那么我们相信此文本已正确编码并可以使用,并且将其转换是愚蠢的事情,但是这种冗长的转换仍然需要放在外面的某个地方htmltoItems


41
Haskell员工请使用统一的字符串:)
Ankur

8
@Ankur:Text正在成为事实上的文本实现。出于遗留原因和简单的原因,String仍然存在,但是对于认真的文本操作,您应该使用Text。
ivanm 2011年

2
@ivanm:如果只有所有那些基于字节串的遗留库会转换!
约翰L

1
@ivanm实际上发生了Text无法使用的情况,我现在只使用了很少的库(Database.MongoDB,Text.Iconv),而且它们都不尊重Text,而且用手进行所有转换都不会感到理智。
Dfr 2011年

2
您最初如何以及在何处获取文本?遇到问题的原因是,您永远不必在不同的编码之间转换Text。首先,您应该使用正确的编码对Text数据进行解码,然后才使用htmlToItems = getItems . parseTags
shang

Answers:


68

ByteStrings主要用于二进制数据,但是如果您只需要ASCII字符集,它们也是处理文本的有效方法。如果您需要处理unicode字符串,则需要使用Text。但是,我必须强调,两者都不能替代,它们通常用于不同的事物:虽然Text表示纯unicode,但ByteString无论何时例如通过套接字或文件传输文本,您仍需要在二进制表示形式中进行编码。。

这是一篇有关unicode基础知识的好文章,它很好地解释了unicode代码点(Text)和编码二进制字节(ByteString)之间的关系:绝对绝对是每个软件开发人员绝对肯定要了解的Unicode和字符套装

您可以使用Data.Text.Encoding模块在两种数据类型之间进行转换,如果使用的是惰性变量,则可以使用Data.Text.Lazy.Encoding(就像您根据错误消息所做的那样)。


这里是另一面,因为我所有的字符串都已经严格:无法匹配预期的类型,Text against inferred type Data.Text.Lazy.Internal.Text所以我从Chunks for Text中找到了,好的,但是最终结果却很丑陋。
Dfr 2011年

5
即使您只需要ASCII,也请不要对“文本”数据使用字节串。将Text用于文本数据,将ByteString用于打包数据结构。如果大家都同意应该在语义上表示什么类型,那么对于使用哪种类型的混淆就更少了,最终,类型之间的转换也将更少。
nomen 2014年

1
“例如,当您通过套接字或文件传输文本时,仍然需要在二进制ByteString表示形式之间进行编码。” 该text软件包实际上提供了已经可以处理文件的功能。

1
是的,该Data.Text.IO模块具有用于处理文件的功能,它们几乎不是您想要的。它们Text从内部ByteString使用系统区域设置的默认字符集进行解码。如果文件碰巧具有其他编码,则将导致运行时错误或垃圾文本。明确地进行编码和解码几乎总是正确的选择。
上山2018年

26

您肯定要对文本数据使用Data.Text。

encodeUtf8是要走的路。这个错误:

无法将预期的类型Data.ByteString.Lazy.Internal.ByteString与推断的类型Data.ByteString.Internal.ByteString进行匹配

表示您正在向代码提供严格的字节串,这需要一个懒惰的字节串。通过以下fromChunks功能可以轻松进行转换:

Data.ByteString.Lazy.fromChunks :: [Data.ByteString.Internal.ByteString] -> ByteString

因此,您需要做的就是在需要fromChunks [myStrictByteString]延迟字节串的位置添加函数。

另一种方法是使用对偶函数来完成转换,该函数toChunks采用一个惰性字节串并给出一个严格的块列表。

您可能想问一些软件包的维护者是否能够提供文本接口来代替字节串接口,或者是否可以提供字节串接口。


5

使用单一的功能csData.String.Conversions

它可以让你之间进行转换StringByteStringText(以及ByteString.LazyText.Lazy),根据输入和预期的类型。

您仍然必须调用它,而不必担心各自的类型。

有关用法示例,请参见此答案

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.