次は(のように:それは毎秒Surely tomorrow
を言って続けて)動作するようです。これは、last [0..]
が実際にMVar
を充填する前にWHFNに強制されていることを確認するためにevaluate
を使用しています
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
- 私は
にフォークスレッドを変更した場合forkIO $ do
let g = last [0..]
putMVar godot g
プログラムを終了します。
ただし、evaluate
はseq
を使用します。決定論的な並列性の文脈では、seq
は評価順序を実際に保証するには不十分であることが常に強調されています。この問題は、モナドのコンテキストで発生していない、または私はより良いtryTakeMVar
が途中で成功したように、コンパイラは、評価の順序を変更することはできません確実にするために
forkIO $ do
let g = last [0..]
g `pseq` putMVar godot g
を使用する必要がありますか?