糟糕的并发,了解monad实例?

时间:2017-02-18 16:20:29

标签: haskell monads continuations

我正在浏览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

我理解延续monad的基本用法,但我正在努力破译这个声明中发生的事情?

1 个答案:

答案 0 :(得分:4)

可能有助于看到C m a实际上只是一个计算 - 在抽象的Action m类型上 - 以a表示的连续传递样式(a -> Action m) -> Action m ,因此数据构造函数C和相应的记录选择器apply只是语法上的粗糙。如果没有它们而没有显式的monad实例,则可以获得以下等效代码。 (请注意,此处类型Cnt 只是延续,而不是延续monad。Control.Monad.Trans.Cont中的延续monad更像是我的CPS类型。)< / p>

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 - 计算(CPS风格),应用于免费cont_b延续。简而言之,括号中的部分是包含在a_to_cps_b中的提供的a - 延续。要将其与cps_a结合使用,我们只需将cps_a应用于此a - 续,即代表a - 由cps_a表示的计算的组合产生a_to_cps_b - 计算的地图b,全部用CPS表示,带有自由变量b_cont。对这个自由变量进行抽象可以得到我们需要的CPS m b

认为可能有助于让整个事情更易于理解,现在您可以回到原始定义,并认识到\a -> apply (f a) k确实是a - f :: a -> C m b的续展版本以表示k - 续集的自由变量b表示。 apply m可用于将a - 计算m应用于此a - 延续,我们留下了一些结合a - 计算的东西m地图fab - 计算,全部用免费b表示 - 名为k的续篇,我们可以lambda-abstract来构造所需的b - 绑定运算符应该返回的计算。