我对this指南中给出的交错函数感到有些困惑。
我有以下数据类型:
data M m r = Atomic (m (M m r)) | Done r
我创建了一个提升函数来获取m a
,在a
内插入Done
,然后将Done a
重新插入m ()
。这形成了Atomic
结构:
atm :: Monad m => m a -> M m a
atm m = Atomic $ liftM Done m
我已将M m
作为Monad
类的实例(基于数据构造函数匹配模式):
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 m1
和next2 <- atm m2
。
据我了解,所有这一切都是从m1
包装器中取出(Atomic m1)
并将其重新插入Atomic
包装器中?这个操作如何交错?
我错过了一些基本的东西吗?代码工作正常,所以我确定这是由于我的困惑。
其余代码:
threadOne :: M IO ()
threadOne = do
atm $ print 1
threadTwo :: M IO ()
threadTwo = do
atm $ print 2
main = do
runThread (interleave threadOne threadTwo)
答案 0 :(得分:2)
你是部分正确的。代码
next1 <- atm m1
接受第一个线程开始的原子操作,并将其插入到合并/交错的线程中。从atm
调用返回的是第一个帖子的继续next1
。
但接下来,我们正在采取第二个主题的行动,说
next2 <- atm m2
因此合并后的线程最终会从第一个线程执行一个动作,然后从第二个线程执行一个动作。因此“交错”。然后我们继续通过
递归地调用interleave
两个延续
interleave next1 next2