简体   繁体   English

将州单子与硬肋的comonad相结合

[英]Combining the state monad with the costate comonad

How to combine the state monad S -> (A, S) with the costate comonad (E->A, E) ? 如何将状态monad S -> (A, S)与硬朗的同伴(E->A, E)结合在一起?

I tried with both obvious combinations S -> ((E->A, E), S) and (E->S->(A, S), E) but then in either case I do not know how to define the operations ( return , extract , ... and so on) for the combination. 我尝试了两种明显的组合S -> ((E->A, E), S)(E->S->(A, S), E)但是无论哪种情况,我都不知道如何定义组合的操作( returnextract ,...等)。

Combining two monads O and I yields a monad if either O or I is copointed, ie have an extract method. 如果将OI共同指定,即使用extract方法,则将两个Monad OI产生Monad。 Each comonad is copointed. 每个对象都被指定。 If both O and I` are copointed, then you have two different "natural" ways to obtain a monad which are presumably not equivalent. 如果同时指定O和I`,那么您有两种不同的“自然”方式来获得单子,这大概是不等效的。

You have: 你有:

unit_O :: a -> O a
join_O :: O (O a) -> O a
unit_I :: a -> I a
join_I :: I (I a) -> I a

Here I've added _O and _I suffixed for clarity; 为了清楚起见,在这里我添加了_O_I后缀; in actual Haskell code, they would not be there, since the type checker figures this out on its own. 在实际的Haskell代码中,它们不会在那里,因为类型检查器可以自行解决。

Your goal is to show that O (IO (I a))) is a monad. 您的目标是证明O (IO (I a)))是单子。 Let's assume that O is copointed, ie that there is a function extract_O :: O a -> a . 假设O是共指的,即存在一个函数extract_O :: O a -> a a- extract_O :: O a -> a

Then we have: 然后我们有:

unit :: a -> O (I a)
unit = unit_O . unit_I
join :: O (I (O (I a))) -> O (I a)

The problem, of course, is in implementing join . 当然,问题在于实现join We follow this strategy: 我们遵循以下策略:

  • fmap over the outer O 在外部O fmap
  • use extract_O to get ride of the inner O 使用extract_O获取内部O
  • use join_I to combine the two I monads 使用join_I合并两个I单子

This leads us to 这导致我们

join = fmap_O $ join_I . fmap_I extract

To make this work, you'll also need to define 为了使这项工作,您还需要定义

newtype MCompose O I a = MCompose O (I a)

and add the respective type constructors and deconstructors into the definitions above. 并将相应的类型构造函数和反构造函数添加到上述定义中。

The other alternative uses extract_I instead of extract_O . 另一种选择是使用extract_I而不是extract_O This version is even simpler: 这个版本更简单:

join = join_O . fmap_O extract_I

This defines a new monad. 这定义了一个新的monad。 I assume you can define a new comonad in the same way, but I haven't attempted this. 我假设您可以用相同的方式定义一个新的comonad,但是我没有尝试过。

As the other answer demonstrates, both of the combinations S -> ((E->A, E), S) and (E->S->(A, S), E) have Monad and Comonad instances simultaneously. 如另一个答案所示,组合S -> ((E->A, E), S)(E->S->(A, S), E)都同时具有Monad和Comonad实例。 In fact giving a Monad/Comonad instance is equivalent to giving a monoid structure to resp. 实际上,给出一个Monad / Comonad实例等效于给出一个monoid结构。 its points ∀rr->f(r) or its copoints ∀rf(r)->r, at least in classical, non-constructive sense (I don't know the constructive answer). 它的点, rr-> f(r)或它的共点 ∀rf(r)-> r,至少在经典的非构造意义上(我不知道构造答案)。 This fact suggests that actually a Functor f has a very good chance that it can be both Monad and Comonad, provided its points and copoints are non-trivial. 这个事实表明,如果Functor f的点和共点不平凡,则它很有可能同时成为Monad和Comonad。

The real question, however, is whether the Monad/Comonad instances constructed as such do have natural computational/categorical meanings. 但是,真正的问题是,如此构造的Monad / Comonad实例是否确实具有自然的计算/分类含义。 In this particular case I would say "no", because you don't seem to have a priori knowledge about how to compose them in a way that suit your computational needs. 在这种特殊情况下,我会说“不”,因为您似乎没有关于如何以适合您的计算需求的方式进行组合的先验知识。

The standard categorical way to compose two (co)monads is via adjunctions. 组成两个(共)单子的标准分类方法是通过附加语。 Let me summarize your situation: 让我总结一下您的情况:

      Fₑ         Fₛ
      -->       -->
Hask  ⊣   Hask  ⊣ Hask
      <--       <--
      Gₑ         Gₛ

Fₜ(a) = (a,t)
Gₜ(a) = (t->a)

Proof of Fₜ ⊣ Gₜ: FₜGₜ的证明:

Fₜ(x) -> y   ≃
(x,t) -> y   ≃
x  -> (t->y) ≃
x  -> Gₜ(y)

Now you can see that the state monad (s->(a,s)) ≃ (s->a,s->s) is the composition GₛFₛ and the costate comonad is FₑGₑ. 现在您可以看到状态monad(s->(a,s))≃(s-> a,s-> s)的成分为GₛFₛ,而同义的同伴为FₑGₑ。 This adjunction says that Hask can be interpreted as a model of the (co)state (co)algebras. 该附加称,Hask可以解释为(共)状态(共)代数的模型。

Now, 'adjunctions compose.' 现在,“附件构成”。 For example, 例如,

FₛFₑ(x) -> y ≃
Fₑ(x)   -> Gₛ(y) ≃
x       -> GₑGₛ(y)

So FₛFₑ ⊣ GₑGₛ. 所以FₛFₑG⊣Gₛ。 This gives a pair of a monad and a comonad, namely 这给出了一个单子和一个共纳,即

T(a) = GₑGₛFₛFₑ(a)
     = GₑGₛFₛ(a,e)
     = GₑGₛ(a,e,s)
     = Gₑ(s->(a,e,s))
     = e->s->(a,e,s)
     = ((e,s)->a, (e,s)->(e,s))

G(a) = FₛFₑGₑGₛ(a)
     = FₛFₑGₑ(s->a)
     = FₛFₑ(e->s->a)
     = Fₛ(e->s->a,e)
     = (e->s->a,e,s)
     = ((e,s)->a, (e,s))

T is simply the state monad with the state (e,s), G is the costate comonad with the costate (e,s), so these do have very natural meanings. T只是带有状态(e,s)的状态单子,G是带有肋骨(e,s)的肋骨,因此它们确实具有非常自然的含义。

Composing adjunctions is a natural, frequent mathematical operation. 合成附加函数是一种自然而频繁的数学运算。 For example, a geometric morphism between topoi (kind of Cartesian Closed Categories which admit complex (non-free) constructions at the 'type level') is defined as a pair of adjunctions, only requiring its left adjoint to be left exact (ie preserves finite limits). 例如,topoi(一种在“类型级别”上接受复杂(非自由)构造的笛卡尔封闭类别)之间的几何形态被定义为一对附加,仅要求其左伴随保持精确 (即保留)。有限的限制)。 If those topoi are sheaves on topological spaces, composing the adjunctions simply corresponds to composing (unique) continuous base change maps (in the opposite direction), having a very natural meaning. 如果这些拓扑是在拓扑空间上的滑轮,则组成附加条件仅对应于组成(唯一)连续的基本变化图(沿相反方向),具有非常自然的意义。

On the other hand, composing monads/comonads directly seems to be a very rare practice in Mathematics. 另一方面,直接合成单子/共母似乎是数学中非常罕见的实践。 This is because often a (co)monad is thought of as a carrier of an (co)algebraic theory, rather than as a model. 这是因为(共)单子通常被认为是(共)代数理论的载体,而不是模型。 In this interpretation the corresponding adjunctions are the models, not the monad. 在这种解释中,相应的附加语模型,而不是单子。 The problem is that composing two theories requires another theory, a theory about how to compose them. 问题在于,组成两个理论需要另一个理论,一个关于如何构成它们的理论。 For example, imagine composing two theories of monoids. 例如,想象一下组成两个类半体的理论。 Then you may get at least two new theories, namely the theory of lists of lists, or ring-like algebras where two kinds of binary operations distribute. 然后,您可能至少会获得两种新理论,即列表列表理论或分布有两种二进制运算的环状代数。 Neither is a priori better/more natural than the other. 先验条件没有一个比另一个更好/更自然。 This is the meaning of "monads don't compose"; 这就是“单子不组成”的意思; it doesn't say the composition cannot be a monad, but it does say you will need another theory how to compose them. 它并没有说合成不可能是单子,而是说您将需要另一种理论来组成它们。

In contrast, composing adjunctions naturally results in another adjunction simply because by doing so you are implicity specifying the rules of composing two given theories. 相比之下,构成附加语自然会导致另一个附加语,这是因为这样做就隐含了指定构成两个给定理论的规则。 So by taking the monad of the composed adjunction you get the theory that also specifies the rules of composition. 因此,通过采用合成辅助词的单子,您可以得到还指定合成规则的理论。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM