【问题标题】:What makes a Bytestring "lazy"?是什么让 Bytestring 变得“懒惰”?
【发布时间】:2021-08-12 10:15:28
【问题描述】:

我正在学习 Haskell,但很难理解惰性 ByteStrings 的工作原理。 Hackage 说“惰性字节字符串使用严格块的惰性列表,使其适用于 I/O 流任务”。相比之下,严格列表存储为一个大数组。

惰性字节串中的这些“块”是什么?您的编译器如何知道块应该有多大?此外,我理解惰性列表背后的想法是您不必存储整个事物,因此允许无限列表等等。但是这个存储是如何实现的呢?每个块是否都有指向下一个块的指针?

非常感谢您的帮助:)

【问题讨论】:

    标签: haskell lazy-evaluation bytestring


    【解决方案1】:

    你可以找到definition of the lazy ByteString here:

    data ByteString = Empty | Chunk {-# UNPACK #-} !S.ByteString ByteString
        deriving (Typeable)
    

    所以Chunk 是一个数据构造函数 - 第一部分是严格的 (!) strict (S.) ByteString,然后是更多的 Chunks 或 @987654332 @ 通过第二个递归(惰性)ByteString 部分。

    请注意,第二部分没有 (!) 那里 - 所以这可以是 GHC thunk (Haskell 中的 lazy 东西)只有在你需要时才会被强制 它(例如 pattern-match 就可以了)。

    这意味着一个懒惰的ByteString 要么是Empty,要么你得到一个严格的(如果你愿意,你可以认为这是已经加载)部分或 lazy 剩余/rest/tail ByteString 的完整字符串。

    关于大小取决于生成这个惰性字节串的代码 - 编译器不会进入这个。

    你可以看到hGetContents

    hGetContents = hGetContentsN defaultChunkSize
    

    defaultChunkSize 定义为 32 * 1024 - 2 * sizeOf (undefined :: Int) - 所以略小于 32kB

    是的,restChunk 的参数)可以看作是指向下一个 ChunkEmpty 的指针(就像 normal em> 列表)。

    【讨论】:

    • 这很有帮助!谢谢!
    • 我想在这个答案中补充一点,使用惰性 ByteString 的主要原因是做惰性 IO。 Lazy IO 有点复杂且难以推理。 告诫讲师
    猜你喜欢
    • 1970-01-01
    • 2016-10-21
    • 2019-05-19
    • 2013-03-15
    • 2019-10-15
    • 1970-01-01
    • 2015-09-06
    • 2012-08-25
    • 1970-01-01
    相关资源
    最近更新 更多