穷人并发,了解monad实例?
Poor mans concurrency, understanding the monad instance?
我 运行 通过 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 的基本用途,但我正在努力破译此声明中发生的事情?
看到 C m a
实际上只是一种计算——基于抽象 Action m
类型——a
以连续传递样式 [=15] 表示可能会有所帮助=],所以数据构造器 C
和相应的记录选择器 apply
只是句法上的废话。在没有它们且没有显式 monad 实例的情况下重写,您将获得以下等效代码。 (注意这里的类型Cnt
只是只是一个continuation,不是continuation monad。Control.Monad.Trans.Cont
中的continuation monad更像我的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
-continuation;但是,给定这个延续,它只是一个 a
-延续,它使用 a_to_cps_b
构造一个 b
-计算(以 CPS 风格),它是适用于免费 cont_b
延续。简而言之,括号中的部分是包含在 a
-continuation 中的提供的 a_to_cps_b
。为了将它与 cps_a
结合起来,我们只需将 cps_a
应用于此 a
-continuation,它表示 cps_a
表示的 a
-计算与产生 b
计算的映射 a_to_cps_b
,全部用 CPS 表示,带有一个自由变量 b_cont
。对这个自由变量的抽象为我们提供了我们需要的 CPS m b
。
我 认为 这可能有助于使整个事情更容易理解,你现在可以回到原来的定义,认识到 \a -> apply (f a) k
确实是一个 a
-f :: a -> C m b
的延续版本,用表示 b
-延续的自由变量 k
表示。 apply m
可用于将 a
-计算 m
应用到此 a
-continuation,我们剩下的是结合 a
-计算的东西m
与从 a
到 b
计算的映射 f
,全部以名为 k
的免费 b
-延续表示,我们可以 lambda-abstract 构造绑定运算符应该 return 所需的 b
-计算。
我 运行 通过 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 的基本用途,但我正在努力破译此声明中发生的事情?
看到 C m a
实际上只是一种计算——基于抽象 Action m
类型——a
以连续传递样式 [=15] 表示可能会有所帮助=],所以数据构造器 C
和相应的记录选择器 apply
只是句法上的废话。在没有它们且没有显式 monad 实例的情况下重写,您将获得以下等效代码。 (注意这里的类型Cnt
只是只是一个continuation,不是continuation monad。Control.Monad.Trans.Cont
中的continuation monad更像我的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
-continuation;但是,给定这个延续,它只是一个 a
-延续,它使用 a_to_cps_b
构造一个 b
-计算(以 CPS 风格),它是适用于免费 cont_b
延续。简而言之,括号中的部分是包含在 a
-continuation 中的提供的 a_to_cps_b
。为了将它与 cps_a
结合起来,我们只需将 cps_a
应用于此 a
-continuation,它表示 cps_a
表示的 a
-计算与产生 b
计算的映射 a_to_cps_b
,全部用 CPS 表示,带有一个自由变量 b_cont
。对这个自由变量的抽象为我们提供了我们需要的 CPS m b
。
我 认为 这可能有助于使整个事情更容易理解,你现在可以回到原来的定义,认识到 \a -> apply (f a) k
确实是一个 a
-f :: a -> C m b
的延续版本,用表示 b
-延续的自由变量 k
表示。 apply m
可用于将 a
-计算 m
应用到此 a
-continuation,我们剩下的是结合 a
-计算的东西m
与从 a
到 b
计算的映射 f
,全部以名为 k
的免费 b
-延续表示,我们可以 lambda-abstract 构造绑定运算符应该 return 所需的 b
-计算。