2017-02-18 50 views
1

我通过this指南运行实现并发,我无法理解这个单子实例:穷人并发性,了解monad实例吗?

data Action m = Atom (m (Action m)) | Fork (Action m) (Action m) | Stop 

newtype C m a = C {apply :: (a -> Action m) -> Action m} 

instance Monad (C m) where 
m >>= f   = C $ \k -> apply m(\a -> apply (f a) k) --? 
return x  = C $ \k -> k x 

我明白延续单子的基本用途,但我挣扎破译这是怎么回事在这个声明?

回答

4

这可能有助于看到一个C m a其实只是一个计算 - 在一个抽象的Action m类型 - 的a在延续传递风格(a -> Action m) -> Action m表示,这样的数据构造C和相应的记录选择apply只是语法起毛。没有它们而没有明确的monad实例重写,你会得到以下等效代码。 (请注意,类型Cnt这里只是的延续,而不是延续单子在Control.Monad.Trans.Cont延续单子更像是我的CPS类型。)

type Cnt m a = (a -> Action m) -- a continuation, not a Cont monad 
type CPS m a = Cnt m a -> Action m 
bind :: CPS m a -> (a -> CPS m b) -> CPS m b 
cps_a `bind` a_to_cps_b = \cont_b -> cps_a (\a -> a_to_cps_b a cont_b) 

或稍微详细:

cps_a `bind` a_to_cps_b = 
    \cont_b -> cps_a (\a -> let cps_b = a_to_cps_b a in cps_b cont_b) 

这是如何工作的?那么,括号内的部分有一个自由变量cont_b这是一个b - 继续;但是,给出了这个延续,它只是一个a-继续,它使用a_to_cps_b来构造一个b -computation(以CPS风格),它被应用于免费的cont_b延续。简而言之,括号中的部分是提供的a_to_cps_b包装在一个a - 续。与cps_a结合起来,我们只是运用cps_aa -continuation,并将代表a -computation通过cps_a与产生一个b -computation地图a_to_cps_b代表的组合,在CPS与自由变量b_cont都表示。通过这个自由变量抽象给我们我们需要的CPS m b

认为这可能有助于使整个事情更容易理解,你现在可以回到原来的定义,认识到\a -> apply (f a) k是一个真正的a -continuation版本的f :: a -> C m b中的自由变量k来表达代表b - 续。 apply m可用于应用a -computation m这个a -continuation,和我们留下的东西,从a结合a -computation m与地图fb -computation,都表示在一个方面免费b - 继续名为k,我们可以使用lambda-abstract来构造所需的b - 计算器,该计算器应该返回绑定操作符。