在论文Tackling the awkward squad中,Simon Peyton Jones提供了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?它已从写入中取出,其范围仅限于当前块,那么它有什么区别?
答案 0 :(得分:4)
问题是,为什么要写入old_hole?它已从写入中取出,其范围仅限于当前块,那么它有什么区别?
不完全。 old_hole
在&#34;范围内&#34;在阅读方。你需要查看newChan
的全貌:
newChan = do {
read <- newEmptyMVar ;
write <- newEmptyMVar ;
hole <- newEmptyMVar ;
putMVar read hole ;
putMVar write hole ;
return (read,write) }
在致电newChan
&#34; old_hole
&#34;之后来自putChan
的{{1}}与MVar
中的hole
相同。随着渠道运营的进展,newChan
总是嵌套在old_hole
的{{1}}中。
我发现链接列表式频道的设计一开始真的难以理解。该论文的插图在展示结构方面做得不错,但基本的想法是读者&#34;剥离&#34;一层MVar来揭示一个价值,而作家则在底部插入价值&#34;&#34;在一堆MVars中,主要指向最底部的一个。
顺便说一下,这是Control.Concurrent.Chan
中使用的设计