完全懒惰了
反复
证明
至
原因
空间
泄漏。
为什么要完全懒惰 -O
向前?我发现自己不相信SPJ的推理 函数式编程语言的实现。声称是在
f = \y -> y + sqrt 4
sqrt 4
每次不必要地重复 f
输入所以我们应该将它漂浮在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
在这种情况下,你可以减少,但通常你不能减少。并命名该功能 (+1)
真是太难看了。