如预期的那样,
foo
仅评估一次(CSE可能会启动)
不,这与CSE无关,它只是惰性评估(又称按需调用)的工作方式:foo
是一种恒定的应用形式,因此只需要一次计算(从thunk转换为WHNF),然后可以简单地进行计算无需进一步计算即可重复使用。之所以在GHCi-8中不再起作用,是因为7.8消除了GHCi中的单态性限制。为什么这是相关的?好吧,trace "eval foo" 5
是type的多态表达式Num a -> a
。多态表达式不能是CAF。因此,您不必按需呼叫,而可以按名称呼叫语义。
再次共享的最简单方法是通过使类型变为单态并添加显式签名来实施CAF:
Prelude Debug.Trace> let foo = trace "eval foo" 5 :: Int in foo + foo eval foo 10