haskell - 为什么完全惰性是默认优化?

标签 haskell ghc

完全的懒惰已经
repeatedly
demonstrated

cause
space
leaks .

为什么从 -O 开始完全懒惰向前?我发现自己不相信 SPJ 的 The Implementation of Functional Programming Languages 中的推理。 .声称是在

f = \y -> y + sqrt 4
sqrt 4每次都不必要地重复 f已输入,因此我们应该将其 float 到 lambda 之外。我同意在小范围内,但既然我们已经看到这种转变在大范围内会导致什么问题,我不认为这是值得的。在我看来,这种转换的好处可以单方面获得**,只需更改本地代码,想要它的程序员应该手动实现它。

你能说服我吗?是 full-laziness实际上真的有用吗?如果您能提供手动实现需要多边合作或非本地转换的示例,我将特别相信。

** 与手动实现的内联和流融合等优化不同,需要模块之间的多边合作和非本地代码更改

最佳答案

至少有一种常见的情况是完全懒惰是“安全的”并且是一种优化。

g :: Int -> Int
g z = f (z+1)
  where f 0 = 0
        f y = 1 + f (y-1)

这真的意味着g = \z -> let {f = ...} in f (z+1)并且,以这种方式编译,将为 f 分配一个闭包在调用它之前。显然这很愚蠢,编译器应该将程序转换为
g_f 0 = 0
g_f y = 1 + g_f (y-1)
g z = g_f (z+1)

无需分配即可调用 g_f .令人高兴的是,完全的惰性转换正是这样做的。

显然,程序员可以避免做出这些不依赖于顶级函数参数的本地定义,但这样的定义通常被认为是好的风格......

另一个例子:
h :: [Int] -> [Int]
h xs = map (+1) xs

在这种情况下,您可以只进行 eta reduce,但通常不能进行 eta reduce。并命名函数(+1)很丑。

关于haskell - 为什么完全惰性是默认优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35115172/

相关文章:

haskell - 查看 Template Haskell 生成的代码的首选方法

haskell - 基于交互式(GHCi)或编译的条件编译

function - `(Integer a) => a -> Bool` 和 ` Integer -> Bool` 之间的区别?

haskell - 无法在 C 中添加自然数的后果

haskell - 简单的 Haskell 实例问题

haskell - 已安装模块的 Pandoc 'Could not find module ...'

haskell - 如何在 Haskell (GHC) 中启用死代码警告

Haskell map函数,返回一个没有零的列表

haskell - 在 Haskell 中开发时查看未公开的库函数

haskell - 如何设置WinGHCi的工作目录