Haskell中没有错误消息

时间:2011-09-23 04:05:15

标签: haskell error-handling

出于好奇,我制作了一个简单的脚本来检查在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中输入这个大数字就会输出数字,所以我不认为这是一个舍入或读数错误。

2 个答案:

答案 0 :(得分:15)

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

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

这可以通过使用固定大小类型(例如:来自Data.Word或Data.Int)或使用整数来使平台独立。

所有这一切,这是一个开始时考虑不周的测试。 Haskell是懒惰的,因此wastedMem n对任何值n消耗的内存量都很小 - 它只是thunk。一旦你试图显示这个结果,它将一次一个地从列表中获取元素 - 首先生成"[12432483483467856487256348746328761,并将列表的其余部分保留为thunk。在第二个值被考虑之前,第一个值可以被垃圾收集(一个恒定空间程序)。

答案 1 :(得分:3)

添加到Thomas的答案,如果你真的想浪费空间,你必须在列表上执行操作,这需要立即在内存中的整个列表。一个这样的操作是排序:

print . sort . wasteMem $ (2^16)

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