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
,...等等)的组合.
如果 或共指向,即有一个方法,则组合两个 monadO
并生成一个 monad 。每个 comonad 都是共指向的。如果两者和 I` 共指,那么您有两种不同的“自然”方式来获取 monad,它们可能不相等。I
O
I
extract
O
你有:
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
组合两个I
monad这导致我们
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,但我还没有尝试过。