Gui*_*rel 5 haskell lazy-evaluation
在关于计时计算的 wiki 页面中,有一个为纯计算计时的示例。核心思想是使用函数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
Run Code Online (Sandbox Code Playgroud)
我想澄清一下函数的使用evaluate,rnf和seq这里。
首先,将evaluate其参数评估为弱头范式,但它的另一个目的似乎是处理评估过程中可能发生的异常。我不确定没有它会发生什么,但我准备假设异常处理需要它。
然后,rnf将值计算为标准形式,以确保整个计算都发生在此处,并且由于调用evaluate. 正如这里所讨论的,这可能是也可能不是人们想要的,因为可能不需要额外的评估。
最后,seq确保rnf x在返回之前将表达式计算为弱头范式return ()。
总结:evaluate处理潜在的异常,深入rnf评估x以确保整个计算是定时的,并seq确保及时rnf x评估。
以下是我的问题:
seq的调用的调用不是多余的rnf吗?rnf为rwhnf? 然后,将在3个电话evaluate,rwhnf并且seq是多余的,这样我可以消除使用最后2和幸福只evaluate?对 的调用seq并不多余,因为rnf x需要评估(到 WHNF)才能评估x到 NF,这就是seq的工作。
是的,我相信是这样:只是
evaluate $ 1 + y
return ()
Run Code Online (Sandbox Code Playgroud)但!如果这里的目的evaluate是处理异常,我认为它不起作用,因为它们rnf x也可以被抛出。如果不是,我看不出有什么好处
rnf (1 + y) `seq` return ()
Run Code Online (Sandbox Code Playgroud)
和 文档都force提出evaluate了一个更简单的替代方案:
evaluate $ force $ 1 + y
return ()
Run Code Online (Sandbox Code Playgroud)
也许该页面是在force可用之前编写的?即便如此,除非我错过了什么,
evaluate $ rnf $ 1 + y
Run Code Online (Sandbox Code Playgroud)
会正确完成这项工作。