将州monad与costate comonad相结合

Bob*_*Bob 5 monads haskell functional-programming category-theory comonad

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

我试图与这两个明显的组合S -> ((E->A, E), S)(E->S->(A, S), E)后来在这两种情况下,我不知道如何定义的操作(return,extract,...等等)的组合.

Eri*_*ter 3

如果 或共指向,即有一个方法,则组合两个 monadO并生成一个 monad 。每个 comonad 都是共指向的。如果两者和 I` 共指,那么您有两种不同的“自然”方式来获取 monad,它们可能不相等。IOIextractO

你有:

unit_O :: a -> O a
join_O :: O (O a) -> O a
unit_I :: a -> I a
join_I :: I (I a) -> I a
Run Code Online (Sandbox Code Playgroud)

为了清楚起见,我在这里添加了_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)
Run Code Online (Sandbox Code Playgroud)

当然,问题在于实施join。我们遵循这个策略:

  • fmap在外层之上O
  • 用于extract_O乘坐内部O
  • 用于join_I组合两个Imonad

这导致我们

join = fmap_O $ join_I . fmap_I extract
Run Code Online (Sandbox Code Playgroud)

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

newtype MCompose O I a = MCompose O (I a)
Run Code Online (Sandbox Code Playgroud)

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

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

join = join_O . fmap_O extract_I
Run Code Online (Sandbox Code Playgroud)

这定义了一个新的单子。我假设你可以用同样的方式定义一个新的comonad,但我还没有尝试过。