如何在现有的 Haskell 代码中从 String 转到 Data.ByteString.Lazy?

Posted

技术标签:

【中文标题】如何在现有的 Haskell 代码中从 String 转到 Data.ByteString.Lazy?【英文标题】:How to go from String to Data.ByteString.Lazy in an existing Haskell code? 【发布时间】:2010-09-15 06:40:44 【问题描述】:

我有一个使用大量字符串的 Haskell 代码,在对其进行分析时,似乎该代码使用大量内存来存储列表 []。解决这个问题的一种方法是使用 Data.ByteString.Lazy 代替 String,但是

这样做时我需要注意什么?,

必须仔细查看代码的哪一部分:折叠、映射、...?

感谢回复

【问题讨论】:

【参考方案1】:

OverloadedStrings 扩展在您使用 GHC 并且正在转换包含大量字符串文字的代码时会很方便。只需将以下内容添加到源文件的顶部:

-# LANGUAGE OverloadedStrings #-

而且您不必在代码中的任何字符串文字上使用B.pack。例如,您可以有以下内容:

equalsTest :: B.ByteString -> Bool
equalsTest x = x == "Test"

如果没有扩展名,这将产生错误,因为您不能在 ByteString[Char] 上使用 ==。通过扩展,字符串字面量的类型为(IsString a) => a,而ByteStringIsString 的一个实例,所以这里的"Test" 被键入为ByteString 并且没有错误。

【讨论】:

我也想过推荐这个,但由于它是语言扩展,可能会破坏可移植性。 在 Haskell 中编写软件的人使用 GHC 以外的东西?哦。 是的,确实如此。例如,有人告诉我,有 Utrecht Haskell 编译器,它有时可以创建更快的代码。 作为扩展,这似乎很安全:它很方便,它使你的代码更干净,而且你总是可以通过一个快速的sed 摆脱它。【参考方案2】:

您应该知道,ByteString 对于迭代 it 元素之类的事情确实很糟糕,但更适合 Concatation 等。

如果您想使用 ByteStrings,您必须将 String 转换为 ByteString,只需执行类似的操作

import Data.ByteString.Lazy as B

并在与它们一起使用的每个函数前面加上 B - String 的大多数函数也适用于 ByteString。请注意 - 您必须将您使用的字符串转换为具有某些功能的 ByteString。

如果您改用Data.ByteString.Lazy.Char8,则可以轻松使用pack,但所有大于255 的字符都将被截断。此外,这种类型更适合二进制数据和安全内存。

编辑:如果你想处理文本字符串,你应该考虑使用包文本。查看here了解更多详情。

【讨论】:

为什么 ByteString “对于迭代之类的东西真的很糟糕”?它归结为一个 8 位整数的向量;与 C char * 完全一样。 map over strict Bytestrings 对目标向量进行一次分配,从源向量中读取每个字节,应用映射函数,并将结果放入内存。一切都是开箱即用的。它受到流融合的影响。我无法想象有什么比这更适合迭代了! 我在学校就是这么想的。 我认为,如果您从 ByteString 的头部添加/删除元素(尤其是添加),它涉及大量的数组复制。但是,是的,我可能错了。 是的。如果你的操作很重,那么理论上链表或惰性字节串比严格的字节串更合适。如果它是重附加的,则 Lazy 字节串将在恒定时间内执行操作。不过,这是一种权衡;尽管追加是常数时间,但您会失去使用纯向量获得的参考局部性。这比 allocate / memcpy 周期快还是慢取决于您的应用程序 - 幸运的是,两者都很容易尝试!

以上是关于如何在现有的 Haskell 代码中从 String 转到 Data.ByteString.Lazy?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Pandas 在现有的 excel 文件中保存新工作表?

如何在现有的 Android 操作系统源中添加额外的项目?

在 Python 3 中从 dbus 迁移到 GDbus

如何在现有的基于 Storyboard 的项目中设置 @EnvironmentObject?

如何在现有的 bios 中实现新功能?

如何在现有的 ios 测试项目中启用 xcode 7 UI 测试