1

在 Haskell 中,考虑到其惰性,将经常计算的值存储为数据成员是否更好,或者在标准的非扩展 Haskell 中不这样做是否安全。

为了更好地理解我的意思,举个例子:

data Image = Image { size :: Int, inverse_size :: RealFrac }

new_image size = Image { size = size, inverse_size = 1.0 / fromIntegral size }

或者我应该在使用它的地方声明它,假设它function经常被调用:

data Image = Image { size :: Int } -- no tainting

something (Image size) =
    let inverse_size = 1.0 / fromIntegral size -- possibly make a function of it
    in ...

作为一种懒惰的语言,并且来自 C++ 模板元编程,我不确定 Haskell 会记住多少这样的计算。

这在运行时速度和存储方面有什么不同吗?

4

1 回答 1

2

非规范化 - 性能权衡不是 Haskell 特有的事情。如果Image您给出的示例类型接近实际,并且您使用大量Images 进行操作,则通过预先计算几乎不会提高性能inverse_size,因为您节省了 1 次将值放在 FPU 堆栈上的操作和 1 次浮点数以 1 个额外的内存负载为代价进行除法(如果与 一起sizesomething函数中使用inverse_size),并且 x2-3 内存使用量增加。这不是一个伟大的成就。

无论如何,给inverse_size你一个机会应该确保这个字段是严格的:

data Image = Image { size :: !Int, inverse_size :: !Float }

否则,这种预先计算肯定是没有意义的。

如果您想知道 GHC 编译器是否自己优化了这些事情,答案是:GHC 能够在一个函数(或多个(通过调用嵌套)函数,如果它们是内联的)中浮动重复计算,但它不会产生数据结构本身中的新字段。

于 2013-04-09T17:49:45.843 回答