6

サイモン・ペイトン・ジョーンズは、厄介な分隊に取り組むという論文で、 Channel.

type Channel a = (MVar (Stream a) , -- Read end
                  MVar (Stream a) ) -- Write end (the hole)

type Stream a = MVar (Item a)

data Item a = MkItem a (Stream a)

今、彼はputChan :: Channel a -> a -> IO ()このような機能を実装しています

putChan (read, write) val
  = do { new_hole <- newEmptyVar ;
         old_hole <- takeMVar write ;
         putMVar write new_hole ;
         putMVar old_hole (MkItem val new_hole) }

上記の関数は、MVar を書き込みから取り出し、空の MVar をそれに入れます。
次に、write から抽出した old_hole に書き込みます。

問題は、なぜ old_hole に書き込むのかということです。それは write から取り出され、そのスコープは現在のブロックのみに制限されています。

4

1 に答える 1

4

問題は、なぜ old_hole に書き込むのかということです。それは write から取り出され、そのスコープは現在のブロックのみに制限されています。

そうではありません。読み取り側old_holeで「範囲内」です。全体像を確認する必要があります。newChan

newChan = do { 
    read <- newEmptyMVar ;
    write <- newEmptyMVar ;
    hole <- newEmptyMVar ;
    putMVar read hole ;
    putMVar write hole ;
    return (read,write) }

したがって、 fromを呼び出しnewChanた直後はinと同じです。そして、チャネル操作が進行するにつれて、それは常にの のどこかにネストされます。old_holeputChanMVarholenewChanold_holeMVarread

リンクされたリスト形式のチャネルのデザインは、最初は頭を悩ませるのが本当に難しいと感じました。その論文のイラストは構造を示すのにまともな仕事をしていますが、基本的な考え方は、読者が MVar のレイヤーを「剥がして」値を明らかにする一方で、ライターは MVar の山の「一番下」に値を挿入し、維持することです。一番下のものへのポインタ。

ちなみにこれはControl.Concurrent.Chanで使われているデザインです

于 2015-01-08T22:52:14.757 に答える