2017-03-02 16 views
3

thisガイドに記載されているインターリーブ機能によって少し混乱します。基本的なスレッド、インターリーブスレッドの混乱?

私は次のデータ型があります:私はm aを取るために昇降機能を作成しました

data M m r = Atomic (m (M m r)) | Done r 

を、Doneaを挿入し、バックm()に再度挿入Done a。これはAtomic構造を形成する:

atm :: Monad m => m a -> M m a 
atm m = Atomic $ liftM Done m 

私は(データコンストラクタに基づいて、パターンマッチ)MonadクラスのM mインスタンスを作りました:

instance (Monad m) => Monad (M m) where 
    return = Done 
    (Atomic m) >>= f = Atomic liftM (>>= f) m 
    (Done r) >>= f = f v 

ネストされた値にアクセスする単純な実装の機能がありますAtomic wrapper内:

runThread :: Monad m => M m a -> m a 
runThread (Atomic m) = m >>= runThread --Extract m and recursively pass to runThread 
runThread (Done r) = return r --Return Done 

次に、次のインターリーブ機能があります。上:混乱の

interleave :: Monad m => M m r -> M m r -> M m r 
interleave (Atomic m1) (Atomic m2) = do 
    next1 <- atm m1 --? 
    next2 <- atm m2 --? 
interleave next1 next2 
interleave (Done _) t2 = interleave t2 
interleave t1 (Done _) = interleave t1 

マイポイントnext1 <- atm m1next2 <- atm m2です。私はそれを理解したよう

、このすべてが(Atomic m1)ラッパーからm1を取り、Atomicラッパーに戻し、それを再挿入されているのですか?この操作はどのようにインタリーブされますか?

ここに基本的なものがありません。コードは正常に動作するので、私はそれが私の混乱のためだと確信しています。

残りのコード:

threadOne :: M IO() 
threadOne = do 
    atm $ print 1 

threadTwo :: M IO() 
threadTwo = do 
    atm $ print 2 

main = do 
    runThread (interleave threadOne threadTwo) 

答えて

2

あなたは部分的に正しいです。コード

next1 <- atm m1 

は、最初のスレッドが開始するアトミックアクションをとり、それをマージ/インターリーブされたスレッドに挿入します。 atmへの呼び出しから返されるものは、その最初のスレッドの続きnext1です。

しかし、次の、我々は

next2 <- atm m2 

ので、マージされたスレッドが最初のスレッドからアクションを実行してしまい、その後、第二のスレッドからの1と言って、第二のスレッドからアクションを取っています。したがって、「インターリーブ」。次に、2つの連続でinterleaveを再帰的に呼び出すことによって、引き続き

interleave next1 next2 
関連する問題