如何在现有的 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
,而ByteString
是IsString
的一个实例,所以这里的"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 位整数的向量;与 Cchar *
完全一样。 map
over strict Bytestrings 对目标向量进行一次分配,从源向量中读取每个字节,应用映射函数,并将结果放入内存。一切都是开箱即用的。它受到流融合的影响。我无法想象有什么比这更适合迭代了!
我在学校就是这么想的。
我认为,如果您从 ByteString 的头部添加/删除元素(尤其是添加),它涉及大量的数组复制。但是,是的,我可能错了。
是的。如果你的操作很重,那么理论上链表或惰性字节串比严格的字节串更合适。如果它是重附加的,则 Lazy 字节串将在恒定时间内执行操作。不过,这是一种权衡;尽管追加是常数时间,但您会失去使用纯向量获得的参考局部性。这比 allocate / memcpy 周期快还是慢取决于您的应用程序 - 幸运的是,两者都很容易尝试!以上是关于如何在现有的 Haskell 代码中从 String 转到 Data.ByteString.Lazy?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Pandas 在现有的 excel 文件中保存新工作表?