用确定性值替换重复的函数应用程序

sof*_*sof 4 haskell

f x y z = [n | n <- z, n > x + y]

f 1 2 [3,4]
Run Code Online (Sandbox Code Playgroud)

x + y要在第一只执行一次,这样连续的通话费由所取代value 3呢?GHCHaskell 是否优化了这项工作,FP为我们带来了参考透明度的优点?

如何追踪证明呢?

Mat*_*hid 9

我不认为计算值会被重用.

这种事情的一般问题是,x + y便宜,但你可以在那里进行一些操作,产生一个非常巨大的结果,你可能不想留在记忆中.这是一种冗长的说法,"这是时间/空间的权衡".

因此,似乎GHC倾向于重复工作,以防丢失的空间无法弥补所获得的时间.

找出肯定的方法是在编译代码时要求GHC转储Core.然后,您可以准确地看到将要执行的内容.(尽管它准备得非常冗长!)哦,并确保你打开优化!(即-O2旗帜.)

如果你将你的功能改写为

f x y z = let s = x + y in [ n | n <- z, n > s ]
Run Code Online (Sandbox Code Playgroud)

现在,s肯定只执行一次.(即每次打电话一次f.每次打电话f都会重新计算s.)

顺便提一下,如果您对保存整个函数的已计算结果感兴趣,那么您正在寻找的搜索词是"memoisation".


Eri*_*ikR 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]
Run Code Online (Sandbox Code Playgroud)

在7.8.3中,我得到以下结果:

  1. ghci的: x y x y [4]
  2. ghc(没有优化): x y x y [4]
  3. ghc -O2: x y [4]

添加trace呼叫可能会影响CSE优化.但这确实表明-O2将提升x+y出循环.