Haskell 中没有错误消息

发布于 2024-12-06 05:47:57 字数 410 浏览 0 评论 0原文

出于好奇,我制作了一个简单的脚本来检查在 Haskell 中构造列表的速度和内存效率:

wasteMem :: Int -> [Int]
wasteMem 0 = [199]
wasteMem x = (12432483483467856487256348746328761:wasteMem (x-1))

main = do
    putStrLn("hello")
    putStrLn(show (wasteMem 10000000000000000000000000000000000))

奇怪的是,当我尝试这个时,它并没有耗尽内存或堆栈空间,它只打印 [199 ],与运行 WasteMem 0 相同。它甚至不打印错误消息...为什么?在 ghci 中输入这个大数字只会打印该数字,因此我不认为这是舍入或读取错误。

Just out of curiosity, I made a simple script to check speed and memory efficiency of constructing a list in Haskell:

wasteMem :: Int -> [Int]
wasteMem 0 = [199]
wasteMem x = (12432483483467856487256348746328761:wasteMem (x-1))

main = do
    putStrLn("hello")
    putStrLn(show (wasteMem 10000000000000000000000000000000000))

The strange thing is, when I tried this, it didn't run out of memory or stack space, it only prints [199], the same as running wasteMem 0. It doesn't even print an error message... why? Entering this large number in ghci just prints the number, so I don't think it's a rounding or reading error.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

违心° 2024-12-13 05:47:57

您的程序使用的数字大于 maxBound :: Int32。这意味着它在不同平台上的表现会有所不同。对于 GHC x86_64 Int 是 64 位(否则为 32 位,但 Haskell 报告仅承诺 29 位)。这意味着你的大得离谱的值(1x10^34)对于我来说被表示为 4003012203950112768 对于 32 位用户来说是零:

GHCI> 10000000000000000000000000000000000 :: Int
4003012203950112768
GHCI> 10000000000000000000000000000000000 :: Data.Int.Int32
0

这可以通过使用固定大小类型(例如:来自 Data.Word 或 Data.Int)或使用 Integer。

话虽如此,这从一开始就是一个构思不佳的测试。 Haskell 是惰性的,因此对于任何值 n 来说,wastedMem n 消耗的内存量都是最小的 - 它只是一个 thunk。一旦您尝试显示此结果,它将一次从列表中抓取一个元素 - 首先生成 "[12432483483467856487256348746328761, 并将列表的其余部分保留为 thunk。第一个值可以被垃圾收集在考虑第二个值之前(恒定空间程序)。

Your program is using a number greater than maxBound :: Int32. This means it will behave differently on different platforms. For GHC x86_64 Int is 64 bits (32 bits otherwise, but the Haskell report only promises 29 bits). This means your absurdly large value (1x10^34) is represented as 4003012203950112768 for me and zero for you 32-bit folks:

GHCI> 10000000000000000000000000000000000 :: Int
4003012203950112768
GHCI> 10000000000000000000000000000000000 :: Data.Int.Int32
0

This could be made platform independent by either using a fixed-size type (ex: from Data.Word or Data.Int) or using Integer.

All that said, this is a poorly conceived test to begin with. Haskell is lazy, so the amount of memory consumed by wastedMem n for any value n is minimal - it's just a thunk. Once you try to show this result it will grab elements off the list one at a time - first generating "[12432483483467856487256348746328761, and leaving the rest of the list as a thunk. The first value can be garbage collected before the second value is even considered (a constant-space program).

不知在何时 2024-12-13 05:47:57

添加到托马斯的答案中,如果您确实想浪费空间,则必须对列表执行操作,这需要立即将整个列表存储在内存中。其中一种操作是排序:

print . sort . wasteMem $ (2^16)

另请注意,几乎不可能估计列表的运行时内存使用情况。如果您想要更可预测的内存基准测试,请创建一个未装箱的数组而不是列表。这也不需要任何复杂的操作来确保所有内容都保留在内存中。对数组中的单个元素进行索引已经确保该数组至少在内存中存在一次。

Adding to Thomas' answer, if you really want to waste space, you have to perform an operation on the list, which needs the whole list in memory at once. One such operation is sorting:

print . sort . wasteMem $ (2^16)

Also note that it's almost impossible to estimate the run-time memory usage of your list. If you want a more predictable memory benchmark, create an unboxed array instead of a list. This also doesn't require any complicated operation to ensure that everything stays in memory. Indexing a single element in an array already makes sure that the array is in memory at least once.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文