Haskell 是评估还是美元!足以在多线程一元上下文中强制一个值,还是需要pseq?

Haskell 是评估还是美元!足以在多线程一元上下文中强制一个值,还是需要pseq?,haskell,concurrency,parallel-processing,strictness,Haskell,Concurrency,Parallel Processing,Strictness,以下内容似乎有效(例如:它每秒钟都在说明天肯定会) 然后程序终止 但是,evaluate使用seq。在确定性并行的上下文中,总是强调seq不足以保证实际的计算顺序。这个问题不是在一元上下文中出现的,还是我应该更好地使用它 forkIO $ do let g = last [0..] g `pseq` putMVar godot g 为了确保编译器不能重新排序求值,从而使tryTakeMVar过早成功?如果我没有完全错,那么将最后[0..]求值到WHNF将

以下内容似乎有效(例如:它每秒钟都在说
明天肯定会

然后程序终止

但是,
evaluate
使用
seq
。在确定性并行的上下文中,总是强调
seq
不足以保证实际的计算顺序。这个问题不是在一元上下文中出现的,还是我应该更好地使用它

    forkIO $ do
        let g = last [0..]
        g `pseq` putMVar godot g

为了确保编译器不能重新排序求值,从而使
tryTakeMVar
过早成功?

如果我没有完全错,那么将
最后[0..]
求值到WHNF将花费无限长的时间,因为
Int
的WHNF意味着您知道确切的数字

putMVar
last[0..]
被计算到WHNF之前不会开始执行(我们知道这会花费很长时间),因为
putMVar
需要调用
evaluate
返回的
RealWorld
-令牌(
s
)。(或者更简单地说:
evaluate
有效。它只有在对WHNF的参数求值后才能完成。)

其中,
seq#
是一个GHC prim函数,它保证仅在对WHNF计算
a
后返回
(#a,s#)
(这是它的目的)。也就是说,只有在将
a
计算为WHNF后,
s
才能用于调用
putMVar
。虽然这些标记纯粹是想象的(“现实世界是非常神奇的…”),但它们受到编译器的尊重,整个IO monad都建立在它之上

因此,在这种情况下,
evaluate
就足够了
evaluate
不仅仅是
seq
:它将IO单体测序与
seq#
测序相结合以产生其效果



事实上,
pseq
版本在我看来有点可疑,因为它最终取决于
lazy
,而
evaluate
最终取决于
seq
和一元令牌传递。我更相信
seq#

pseq
的要点是确保在父线程使用
par
触发计算后,它不会立即尝试评估触发的计算本身的结果,而是先执行自己的工作。有关示例,请参见。当您更明确地使用并发时,不需要
pseq

    forkIO $ do
        let g = last [0..]
        putMVar godot g
    forkIO $ do
        let g = last [0..]
        g `pseq` putMVar godot g
evaluate :: a -> IO a
evaluate a = IO $ \s -> seq# a s
--                     this    ^

putMVar (MVar mvar#) x = IO $ \ s# ->
--           which is used here ^^
    case putMVar# mvar# x s# of
--         is needed here ^^
        s2# -> (# s2#, () #)