f x y z = [n | n <- z, n > x + y]
f 1 2 [3,4]
x + y
首先只执行一次,以便后续调用被value 3
代替? GHC
Haskell对FP的这项工作进行了优化,为我们带来了参考透明度的优点吗?
如何追踪证明呢?
答案 0 :(得分:9)
我认为计算出的值将被重用。
这种事情的一般问题是,x + y
很便宜,但你可以在那里进行一些操作,产生一个完全浩大的结果,你可能不想要留在记忆中。这是一种冗长的说法,“这是时间/空间的权衡”。
正因如此,似乎GHC倾向于不重复工作,以防丢失的空间无法弥补所获得的时间。
确定的方法是在编译代码时要求GHC转储Core。然后,您可以准确地看到将要执行的内容。 (尽量准备它非常详细!)哦,并确保你打开优化! (即-O2
标志。)
如果您将功能改为
f x y z = let s = x + y in [ n | n <- z, n > s ]
现在s
肯定只执行一次。 (即,每次拨打f
一次。每次拨打f
时,它仍会重新计算s
。)
顺便提一下,如果您对保存整个函数的已计算结果感兴趣,那么您正在寻找的搜索词是“memoisation”。
答案 1 :(得分:6)
将会发生什么取决于您是使用ghci还是ghc然后,如果您正在编译代码,那么正在使用什么优化级别。
以下是测试评估的一种方法:
import Debug.Trace
f x y z = [n | n <- z, n > tx x + ty y]
where tx = trace "x"
ty = trace "y"
main = print $ f 1 2 [3,4]
使用7.8.3我得到以下结果:
x y x y [4]
x y x y [4]
x y [4]
添加trace
调用可能会影响CSE优化。但这确实表明-O2会将x+y
提升出循环。