假设我有
f :: Int -> MyType
f i = ......
voxel :: MyType
voxel = f 2
function1 :: Double -> MyType -> MyOtherType
function1 x w = ......
function2 :: Double -> MyOtherType
function2 y = function1 y voxel
现在,假设我调用function2
两次,例如function2 1.0
然后function2 2.0
(我在OpenGL
上下文中,MyOtherType
是要绘制的图形元素,用户可以使用键盘更改y
(。
那么,在function2
的第二次调用中,哈斯克尔会重新评估voxel
吗?
如果我遇到这种情况,例如 C 语言,我会在voxel
中放一个printf
来知道答案,但我不能用纯粹的 Haskell 函数做这样的事情(我可以吗?
Haskell没有说会发生什么。
GHC不会重新评估voxel
;一般来说,let
和where
绑定值最多被评估一次。(但请记住,类多态值的行为类似于函数,其中选择实例是函数应用程序,并且这些函数调用不会被记住,因此显然良性的类多态绑定可能会导致许多重新评估。
你可以用Debug.Trace.trace
放一个"printf
",但这应该仅用于教育和调试目的。
import Debug.Trace
voxel = trace "evaluated voxel" $ f 2
它可能,也可能不是,这取决于使用情况。评估后,它将保持评估状态,直到它被垃圾回收。只要你在某处有对它的引用,它就不能被垃圾回收。
为什么GHC允许垃圾回收顶级"常数"?举个人为的例子,想象一下我有类似的东西
nats :: [Integer]
nats = [0..]
然后是另一个索引到 nats
的函数。如果 GHC 无法收集nats
,它必须将列表存储[1..n]
(其中n
是索引的值(,即使我没有使用大部分列表。