Haskell 可怜的人,理解monad实例吗?
我正在浏览《并发实现指南》,但在理解此monad实例时遇到了问题:Haskell 可怜的人,理解monad实例吗?,haskell,monads,continuations,Haskell,Monads,Continuations,我正在浏览《并发实现指南》,但在理解此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 -&
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
我理解延续单子的基本用法,但我正在努力破解这个声明中发生了什么 我们可以看到,
cma
实际上只是一个计算,在一个抽象的Action m
类型上,一个a
以连续传递样式(a->Action m)->Action m
表示,因此,数据构造函数C
和相应的记录选择器apply
只是语法上的漏洞。在没有它们和显式monad实例的情况下重写,您将得到以下等效代码。(请注意,这里的类型Cnt
只是一个延续,而不是延续单子。Control.monad.Trans.Cont中的延续单子更像我的CPS
类型。)
或者更详细一点:
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样式),应用于免费的延续。简言之,括号中的部分是所提供的a_至
,用a
-续篇包装起来。为了将其与cps\u a
相结合,我们只需将cps\u a
应用于该a
延拓,它表示由cps\u a
表示的a
-计算与产生b
计算的映射a\u-To\u-cps\u-b
的组合,所有都用CPS表示,带有一个自由变量b_cont
。对这个自由变量进行抽象,可以得到我们需要的CPS mb
我认为这可能有助于使整个事情更容易理解,现在您可以回到原始定义,认识到\a->apply(fa)k
实际上是f::a->cmb
的a
延拓版本,用表示b
延拓的自由变量k
表示apply m
可用于将a
-计算m
应用于此a
-延续,剩下的是将a
-计算m
与从a
到b
计算的映射相结合的东西,所有这些都表示为名为k
的自由b
-连续,我们可以对其进行lambda抽象,以构造所需的b
-计算,bind操作符应返回该计算 我们可以看到,cma
实际上只是一个计算,在一个抽象的Action m
类型上,一个a
以连续传递样式(a->Action m)->Action m
表示,因此,数据构造函数C
和相应的记录选择器apply
只是语法上的漏洞。在没有它们和显式monad实例的情况下重写,您将得到以下等效代码。(请注意,这里的类型Cnt
只是一个延续,而不是延续单子。Control.monad.Trans.Cont
中的延续单子更像我的CPS
类型。)
或者更详细一点:
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样式),应用于免费的延续。简言之,括号中的部分是所提供的a_至
,用a
-续篇包装起来。为了将其与cps\u a
相结合,我们只需将cps\u a
应用于该a
延拓,它表示由cps\u a
表示的a
-计算与产生b
计算的映射a\u-To\u-cps\u-b
的组合,所有都用CPS表示,带有一个自由变量b_cont
。对这个自由变量进行抽象,可以得到我们需要的CPS mb
我认为这可能有助于使整个事情更容易理解,现在您可以回到原始定义,认识到\a->apply(fa)k
实际上是f::a->cmb
的a
延拓版本,用表示b
延拓的自由变量k
表示apply m
可用于将a
-计算m
应用于此a
-延续,剩下的是将a
-计算m
与从a
到b
计算的映射相结合的东西,所有这些都表示为名为k
的自由b
-连续,我们可以对其进行lambda抽象,以构造所需的b
-计算,bind操作符应返回该计算