`evaluate`,`rwhnf`和`seq`及其对应的“深层”之间有什么区别?

问题描述 投票:4回答:1

the wiki page about timing computations中,有一个定时纯计算的示例。核心思想是使用函数evaluaternfseq以确保在两次调用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

我想在这里澄清功能evaluaternfseq的使用。

[首先,evaluate将其参数评估为弱头范式,但似乎其另一个目的是处理评估期间可能发生的异常。我不确定如果没有它会发生什么,但是我已经准备好假定异常处理需要它。

然后,rnf将值评估为标准形式,以确保整个计算在此处进行,并且不会由于调用evaluate而以弱头标准形式保留未评估的位。正如here所讨论的,这可能是或可能不是人们想要的,因为可能没有必要进行额外的评估。

最后,seq确保在返回rnf x之前,将表达式return ()的求值形式为弱头正态形式。

总结:evaluate处理潜在的异常,rnf深入评估x以确保整个计算是定时的,seq确保及时评估rnf x

这是我的问题:

  1. seq的调用与对已经将值评估为标准格式的rnf的调用是否冗余?
  2. [如果我希望将评估时间定为弱头正常形式而不是正常形式,我可以简单地将rnf替换为rwhnf吗?那么这3个调用evaluaterwhnfseq是否多余,这样我就可以消除对后两个调用的使用,而只对evaluate感到满意?
haskell lazy-evaluation
1个回答
0
投票
  1. seq的调用不是多余的,因为需要评估(对WHNF的rnf x才能将x评估为NF,这是seq的工作。

  2. 是的,我相信是这样:只是

    evaluate $ 1 + y
    return ()
    

但是!如果evaluate的目的是处理异常,我认为它不起作用,因为它们也可以从rnf x中抛出。如果不是,那么我看不到好处

rnf (1 + y) `seq` return ()

[forceforce文档都提出了一个更简单的选择:

evaluate

也许该页面是在evaluate $ force $ 1 + y return () 可用之前写的?即使这样,除非我错过了什么,

force

将正确完成这项工作。

© www.soinside.com 2019 - 2024. All rights reserved.