2

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..]スレッド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時期尚早に成功しますか?

4

2 に答える 2

1

のポイントはpseq、親スレッドが で計算を開始した後、parすぐに開始された計算自体の結果を評価しようとせず、代わりに最初に独自のジョブを実行することを保証することです。例については、ドキュメントを参照してください。並行性をより明示的に使用している場合は、必要ありませんpseq

于 2016-09-25T21:25:41.707 に答える