可不可以在Haskell中写一个函数,统计n个字符的字符串占用的字节数?

Can we write a function in Haskell to measure the number of bytes that a string of n characters occupies?

假设我有字符串

"abc"

并且我想计算它在内存中占用的字节数。

我能做到:

import Data.Bits
finiteBitSize ("abc" :: [Char])

但这会中断,因为 [Char] 不是该函数支持的类型。 (它也是位而不是字节,但重点是描绘我正在寻找的图片)。

我的问题是:我们可以在Haskell中写一个函数来测量一个n个字符的字符串占用的字节数吗?

这很复杂。

让我们谈谈 GHC,具体来说 String,假设这件事已经过全面评估,所以我们没有以 GC 友好的方式迭代使用它,我们也没有开始延迟评估并存储一个代表巨大数据结构的微小 thunk。

在做出所有这些简化假设之后,我们需要了解一些定义。

type String = [Char]
data [a] = [] | a : [a] -- pseudosyntax
data Char = C# Char# -- I'm guessing, couldn't find a canonical source

现在我们将使用一些经验法则。第一:未装箱的东西(如Char#)通常存储在机器字中。我们生活在一个 64 位机器的世界中,所以 Char# 可能是 8 个字节,即使它可能只使用它的底部 4 个字节。第二:data constructors是一个word表示是哪个constructor,再加一个word指向各个字段。

现在我们准备好了。

空字符串是[],构造函数一个词,字段没有词,所以总共一个词。

非空字符串是c : cs,所以:构造函数一个词,一个词指向c,一个词指向cs,一个词对于 C# 构造函数,一个词对于 Char#。这是 5 个单词加上我们 cs.

需要的单词

所以对于长度为 n 的 String,我们有 5*n 个词来表示 String 的正文,还有一个额外的词用于终止 []。实际上每个字符 40 个字节!哎呀。

现在您知道为什么像 Text(或者,在适当的时候,ByteString)这样的打包表示如此重要。

有一个名为 ghc-datasize 的 Haskell 程序包,它允许您计算每个 Haskell 值 实际 占用的内存。您甚至可以在官方 Hackage 文档中看到如何计算字符串大小的示例:

要计算 String 的长度,您需要使用以下函数:

recursiveSize :: a -> IO Word

看起来像这样:

ghci> recursiveSize $!! "foobar"
240