5

如何将 state monadS -> (A, S)与 costate comonad结合起来(E->A, E)

我尝试了两种明显的组合S -> ((E->A, E), S)(E->S->(A, S), E)但是在任何一种情况下,我都不知道如何为组合定义操作(return, extract, ... 等等)。

4

2 回答 2

3

结合两个 monadOI产生一个 monad,如果其中一个OI是共指的,即有一个extract方法。每个comonad是copointed。如果两者O和 I` 是共指的,那么你有两种不同的“自然”方式来获得一个可能不等价的单子。

你有:

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

为了清楚起见,我在这里添加了_O后缀_I;在实际的 Haskell 代码中,它们不会存在,因为类型检查器会自行计算出来。

你的目标是证明这O (I O (I a)))是一个单子。让我们假设它O是共指的,即有一个函数extract_O :: O a -> a

然后我们有:

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

当然,问题在于实施join. 我们遵循以下策略:

  • fmap在外面O
  • 用来extract_O搭便车O
  • 用于join_I结合两个Imonad

这导致我们

join = fmap_O $ join_I . fmap_I extract

为了使这项工作,您还需要定义

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

并将各自的类型构造函数和解构函数添加到上面的定义中。

另一种替代方法是使用extract_I而不是extract_O. 这个版本更简单:

join = join_O . fmap_O extract_I

这定义了一个新的 monad。我假设您可以以相同的方式定义一个新的共单,但我没有尝试过。

于 2016-10-04T00:10:41.397 回答
3

正如另一个答案所示,这两种组合都S -> ((E->A, E), S)同时(E->S->(A, S), E) 具有 Monad 和 Comonad 实例。事实上,给一个 Monad/Comonad 实例相当于给一个 monoid 结构。它的∀rr->f(r) 或它的共点∀rf (r)->r,至少在经典的、非建设性的意义上(我不知道建设性的答案)。这一事实表明,实际上 Functor f 很有可能既可以是 Monad 又可以是 Comonad,只要它的点和共点是非平凡的。

然而,真正的问题是这样构造的 Monad/Comonad 实例是否具有自然的计算/分类意义。在这种特殊情况下,我会说“不”,因为您似乎没有 关于如何以适合您的计算需求的方式组合它们的先验知识。

组成两个(共)单子的标准分类方法是通过附加词。让我总结一下你的情况:

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

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

Fₜ ⊣ Gₜ 的证明:

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

现在你可以看到状态单子 (s->(a,s)) ≃ (s->a,s->s) 是合成 GₛFₛ 而并列共子是 FₑGₑ。这个附加词说 Hask 可以解释为(共)态(共)代数的模型。

现在,“附加组成”。例如,

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

所以 FₛFₑ ⊣ GₑGₛ。这给出了一对monad和comonad,即

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 只是带有状态 (e,s) 的状态单子,G 是带有并列 (e,s) 的并列共单子,所以这些确实具有非常自然的含义。

组成附加语是一种自然的、频繁的数学运算。例如, topoi(一种允许在“类型级别”上进行复杂(非自由)构造的笛卡尔封闭类别)之间的几何态射被定义为一对附属物,只要求其左附属物保持精确(即保留有限的限制)。如果这些topoi 是拓扑空间上的滑轮,那么组成附属词只对应于组成(唯一的)连续碱基变化图(在相反方向上),具有非常自然的意义。

另一方面,直接组合单子/comonads 似乎是数学中非常罕见的实践。这是因为(共)单子通常被认为是(共)代数理论的载体,而不是模型。在这种解释中,相应的附加词模型,而不是单子。问题是组合两个理论需要另一个理论,一个关于如何组合它们的理论。例如,想象组成两个幺半群理论。然后你可能会得到至少两个新的理论,即列表的列表理论,或两种二元运算分布的环状代数。也不是先验的比其他更好/更自然。这就是“monads don't compose”的意思;它并不是说组合不能是单子,但它确实说你需要另一种理论来组合它们。

相反,组合附加语自然会导致另一个附加语,因为这样做是在隐含地指定组合两个给定理论的规则。因此,通过采用组合附加词的单子,您可以获得同时指定组合规则的理论。

于 2017-01-02T14:56:00.827 回答