【问题标题】:In Haskell, will calling length on a Lazy ByteString force the entire string into memory?在 Haskell 中,在 Lazy ByteString 上调用 length 会强制整个字符串进入内存吗?
【发布时间】:2011-01-31 19:18:31
【问题描述】:

我正在使用惰性字节串读取一个大型数据流,并且想知道在解析它时是否还有至少 X 个字节可用。也就是说,我想知道字节串是否至少有 X 个字节长。

在其上调用length 会导致整个流被加载,从而破坏使用惰性字节串的目的吗?

如果是,那么后续是:如何在不加载整个流的情况下判断它是否至少有 X 个字节?

编辑:最初我在读取文件的情况下询问,但了解有更好的方法来确定文件大小。我需要的最终解决方案不应该依赖于惰性字节串源。

【问题讨论】:

    标签: haskell lazy-evaluation bytestring


    【解决方案1】:

    是的。

    length . take x.

    【讨论】:

    • 谢谢。所以答案是肯定的,使用length会将整个字符串加载到内存中?
    • 是的,长度将强制整个列表并“加载:它”。因此,采取“采取”形式的对策
    • 所以,要清楚我们都明白,是的,长度会强制字符串进入内存,所以如果你先调用 take x,那么至少你只是强制前 x 个字节进入内存。跨度>
    • @MtnViewMark:它可能会强制超过 x 个字节,因为惰性字节串的严格性是在每个块的基础上发生的。强制块的第一个字符也会强制块的其余部分。
    • 对不起,简短的回答,我写得很快,没有时间回来扩展它。是的,length 将强制整个字符串,而length . take x 将仅强制包含第一个 x 字节的块,这可能超过 x 字节总数。我认为默认的块大小在 31kB 附近。
    【解决方案2】:

    您没有使用hFileSize :: Handle -> IO Integer 来获取文件长度是否有原因?

    【讨论】:

    • 是的,因为输入可能实际上不是文件,而是网络流。我对数据的实际长度不感兴趣,但对是否有足够的数据使内容有效(或在这种情况下数据损坏时被截断)感兴趣。
    • 在这种情况下,地球上没有任何程序可以在不读到最后的情况下找到流的长度。
    【解决方案3】:

    编辑:抱歉。我想我在想字节串是列表。字节串没有 genericLength。

    length 是严格的,因为它返回的类型 Int 是严格的。您可以使用来自 Data.List 的 genericLength 并导入一个定义惰性 Peano 数字并为您提供 Num 实例的库,例如 numbers 库:

    这会让你以你想要的方式表达你的功能,但 ehemient 的答案在功能上是相同的,并且不需要导入新的库。

    我刚刚在这里写了一篇关于这个主题的博文,如果这听起来像是你可能感兴趣的方法:

    http://coder.bsimmons.name/blog/2010/03/lazy-arithmetic-in-haskell/

    【讨论】:

    • ByteString 不附带其genericLength。你需要自己写一个。
    • 某处(可能在 Hackage 上,虽然我现在找不到)我遇到了一个“分块”自然数类型,类似于 data Nat = Zero | Sum Integer Nat,它比可能是基于take 的解决方案。
    【解决方案4】:

    它必须迭代整个字符串,但是如果您不在其他任何地方保留对整个惰性字节字符串的引用,我相信它应该能够释放字符串的头部,因为它向尾部前进.

    【讨论】:

      猜你喜欢
      • 2011-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多