Haskell在根据此值调用函数时是否重新计算值?

时间:2018-04-18 17:03:10

标签: haskell

假设我有

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函数(可以吗?)。

2 个答案:

答案 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}没有使用大部分列表。