以下似乎有效(如:它Surely tomorrow
每秒都在说)
import Control.Concurrent
import Control.Concurrent.MVar
import Control.Exception (evaluate)
main :: IO ()
main = do
godot <- newEmptyMVar
forkIO $ do
g <- evaluate $ last [0..]
putMVar godot g
let loop = do
threadDelay $ 10^6
g <- tryTakeMVar godot
case g of
Just g -> return ()
Nothing -> putStrLn "Surely tomorrow." >> loop
loop
这用于evaluate
确保last [0..]
在填充之前实际上强制 WHFN MVar
- 如果我将分叉线程更改为
forkIO $ do
let g = last [0..]
putMVar godot g
然后程序终止。
但是,evaluate
使用seq
. 在确定性并行的上下文中,总是强调这seq
不足以真正保证评估顺序。这个问题不会出现在单子上下文中,还是我应该更好地使用
forkIO $ do
let g = last [0..]
g `pseq` putMVar godot g
以确保编译器不能重新排序评估因此tryTakeMVar
过早成功?