在the wiki page about timing computations中,有一个定时纯计算的示例。核心思想是使用函数evaluate
,rnf
和seq
以确保在两次调用1 + y
之间执行所需的计算(在下面的示例中为getCPUTime
):
time :: (Num t, NFData t) => t -> IO ()
time y = do
start <- getCPUTime
replicateM_ lim $ do
x <- evaluate $ 1 + y
rnf x `seq` return ()
end <- getCPUTime
我想在这里澄清功能evaluate
,rnf
和seq
的使用。
[首先,evaluate
将其参数评估为弱头范式,但似乎其另一个目的是处理评估期间可能发生的异常。我不确定如果没有它会发生什么,但是我已经准备好假定异常处理需要它。
然后,rnf
将值评估为标准形式,以确保整个计算在此处进行,并且不会由于调用evaluate
而以弱头标准形式保留未评估的位。正如here所讨论的,这可能是或可能不是人们想要的,因为可能没有必要进行额外的评估。
最后,seq
确保在返回rnf x
之前,将表达式return ()
的求值形式为弱头正态形式。
总结:evaluate
处理潜在的异常,rnf
深入评估x
以确保整个计算是定时的,seq
确保及时评估rnf x
。
这是我的问题:
seq
的调用与对已经将值评估为标准格式的rnf
的调用是否冗余?rnf
替换为rwhnf
吗?那么这3个调用evaluate
,rwhnf
和seq
是否多余,这样我就可以消除对后两个调用的使用,而只对evaluate
感到满意?对seq
的调用不是多余的,因为需要评估(对WHNF的rnf x
才能将x
评估为NF,这是seq
的工作。
是的,我相信是这样:只是
evaluate $ 1 + y
return ()
但是!如果evaluate
的目的是处理异常,我认为它不起作用,因为它们也可以从rnf x
中抛出。如果不是,那么我看不到好处
rnf (1 + y) `seq` return ()
[force
和force
文档都提出了一个更简单的选择:
evaluate
也许该页面是在evaluate $ force $ 1 + y
return ()
可用之前写的?即使这样,除非我错过了什么,
force
将正确完成这项工作。