假设我有
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
时,Haskell会重新评估voxel
吗?
如果我遇到这样的情况,例如C语言,我会在printf
中设置一个voxel
来了解答案,但我无法做到这一点纯Haskell函数(可以吗?)。
答案 0 :(得分:12)
哈斯克尔并没有说出会发生什么。
GHC不会重新评估voxel
;通常,let
- 和where
- 绑定值最多只评估一次。 (虽然请记住,类 - 多态值的行为类似于函数,选择一个实例是函数应用程序,并且这些函数调用没有被记忆,因此显然良性的类多态绑定可能会导致许多重新评估。)
你可以放一个" printf
"使用Debug.Trace.trace
,但这仅用于教育和调试目的。
import Debug.Trace
voxel = trace "evaluated voxel" $ f 2
答案 1 :(得分:1)
它可能,它可能不会,它取决于使用情况。一旦评估完毕,它将一直保持评估状态,直到它被垃圾收集为止。只要你在某个地方引用它,它就不能被垃圾收集。
为什么GHC允许顶级"常数"被垃圾收集?对于一个人为的例子,假设我有类似
的东西nats :: [Integer]
nats = [0..]
然后另一个索引到nats
的函数。如果GHC无法收集nats
,则必须存储列表[1..n]
(其中n
是已编入索引的值),即使我是{m}没有使用大部分列表。