使用deepSeq
. 它就像seq
. 你会像这样合并它:
myForkedProcess :: IORef [[Color]] -> IO ()
myForkedProcess ref = do let colors = takesAgesToRun
deepSeq colors $ writeIORef ref colors
这将强制在“writeIORef”调用之前对“颜色”进行全面评估。
为了使其工作,您将需要NFData
一个Color
. 具体如何写取决于颜色的定义,但这里有两个例子:
-- just for reference
data Color = Color Double Double Double
instance NFData Color where
rnf (Color r g b) = r `seq` g `seq` b `seq` ()
-- closer to the likely actual implementation for Color
data Color2 = Color2 !Double !Double !Double
instance NFData Color2 where
-- the default implementation is fine
例如Color
,您需要确保颜色的所有组件都被完全评估[1],只要 Color 是。这就是seq
s所做的。我们可以在这里使用seq
代替,deepSeq
因为我们知道每个组件都是 a Double
,因此由 seq 完全评估。deepSeq
如果组件是更复杂的数据类型,那么我们在编写 NFData 实例时需要使用。
在Color2
它有点简单。由于 bang 模式,我们知道组件在何时被完全评估Color2
。这意味着我们可以使用默认实现,它评估Color2
为弱头部正常形式,由于 bang 模式被完全评估。
rnf
主要在与 Control.Parallel.Strategies 结合使用时有用。这是当前的定义deepSeq
deepseq :: NFData a => a -> b -> b
deepseq a b = rnf a `seq` b
deepseq 所做的只是调用rnf
并保证其输出 () 被评估。这确实是rnf
直接使用的唯一方法。
[1] Haskell 只提供了两种评估东西的通用方法:模式匹配和seq
. 其他一切都建立在其中之一或两者之上。对于 NFData Color 实例,Color
首先通过与构造函数的模式匹配将其评估为 WHNF Color
,然后通过 seq 评估组件。
当然,还有第三种高度专业化的方法来评估东西: main :: IO ()
即将执行一个函数来评估()
.