什么是Comonad,它们有什么用?


16

最近,我一直在整理关于Monads工作原理的知识。还向我介绍了'Comonad'的概念,它被描述为monad 逆对。但是,我不可能把头缠住它。

为了了解Monad,我为自己做了一个比喻:

Monads可以看作是“构建表达传送带的蓝图”。

要定义一个新的Monad(一种新型的传送带系统),您需要定义:

  1. 一种在传送带上放置东西的方法,例如“启动”传送带。(称为unitreturn
  2. 将作为传送带一部分的机器(表达式)连接到传送带的一种方式。(称为joinbind>>=)。

(第三项操作是将当前的传送带取走,将其内含物扔掉,然后启动一个新的传送带,称为>>,但很少使用。)

为了使机器和输送机正常工作,您需要确保:

  1. 如果将某些东西放在传送带上并使其通过机器,则输出应与手动将其通过机器时的输出相同。(左身份)
  2. 如果要将传送带放在已经存在的传送带之间,则不应以顶部带有传送带的传送带结尾,而应使用一条更长的传送带。 (正确身份)
  3. 如果您手动使用机器A,然后将结果传递到连接传送带的BC,或者如果您使用机器,将结果传递给连接的AB,然后手动将结果传递给C,则对于输出无所谓。 >> = b)>> = c)应该与(a >> =(b >> = c))相同(关联性)

最简单的传送带就是那种只接受输入并始终继续到下一个表达式的传送带。这就是“管道”。

另一种可能性是,只有在满足该条件的条件下,才让它通过下一台机器。这意味着,如果在它们之间的某些表达式中,该值更改为不再允许的值,则将跳过其余的表达式。这就是“也许”单子在Haskell中所做的事情。

您还可以在将值传递到计算机之前或之后对值执行其他特殊的条件性复制/更改规则。一个示例:解析器(此处,如果表达式返回“失败”结果,则将表达式之前的值 用作输出)。

当然,这个比喻不是完美的,但我希望它能很好地说明单子的工作原理。

但是,我很难理解这种类比,以理解Comonads。我从互联网上发现的少量信息中得知Comonad定义了以下信息:

  • extract,这与的相反return,也就是说,它 Comonad中取出一个值。
  • duplicate,这与的倒数相同join,也就是说,它从一个中创建了两个Comonad。

但是,如果我们只能从它们中提取或复制它们,该如何实例化Comonad?以及如何实际使用它们?我已经看到了这个非常了不起的项目以及有关它的讨论(很遗憾,我对此了解很少),但是我不确定Comonad到底提供了部分功能。

什么是Comonad?它们有什么用?如何使用它们?它们可食用吗?


2
“如果我们只能从它们中提取或复制它们,如何实例化Comonad?” -我将用一个问题回答您的问题:如果您只能将值放入其中并进行序列计算,那么如何使用Monad?
本杰明·霍奇森

1
IOHaskell运行时系统是monad的“位于传送带末端的机器”(另外:在讨论monad时,我找不到类似的帮助)mainunsafePerformIO当然也有。如果您想将Maybemonad看作是“在传送带末端的机器”,则可以使用maybe
本杰明·霍奇森

1
但是,如果您想在一系列cobind应用程序的开头生成一个comonadic值,那么请反过来说,必须有一些函数可以对comonad的内部表示起作用。
本杰明·霍奇森

2
comonad或单子的具体实例可以清楚必须实现类型类比要求的只是更多的功能
JK。

2
如果您不从范畴理论/数学角度解决这个问题,那不是很有用,但我想指出,共鸣不是单反的对偶而是对
约尔格W¯¯米塔格

Answers:


11

就像单子一样,共语是范畴论中的数学结构。副词在这里很常见,用来表示您所说的“逆”(尽管我不认为纯粹的数学家会同意单词的选择)。

在范畴论中,有categories,简要地归纳了objects(任何类型或性质的内部结构无关)的集合,以及arrows这些对象之间的集合。为了使某些事物成为类别,箭头必须遵循一些定律(左/右身份和关联性),但这在这里并不是很重要。

现在,范畴论既是非常抽象的/难以理解又是巨大的。遍历所有内容都花了很多时间(而且我还没有正式学习它,我只知道一些基础知识),但是使用了一个称为a的概念dual。基本上,对于每个类别,您都可以opposite category通过执行相同的操作但“反转所有箭头” 来构造一个。这是一个非常幼稚的定义,但是很难总结。在类别C中,事物的对偶在相反的类别C_op中基本上是相同的事物(还头疼吗?)

无论如何,如果您在某个类别上有一个monad(例如,类别可以是某个类别,其中对象是某种编程语言中的类型,而箭头是这些类型之间的函数),那么comonad基本上是同一件事,只有您自己扭转了所有箭头(在这种情况下有点像扭转功能签名)。

更多的“动手”的说明(虽然不是超级动手)中可以找到这个埃里克·梅杰和布赖恩·贝克曼在那里他们正在讨论对偶的概念,并进行讨论埃里克如何着手“反向箭头”为IEnumerable<T>在C#中,当创建响应式框架和IObservable<T>(据我所知,我很高兴得到纠正,基本上是一个列表组合实例)。

视频中提到的comonads的另一个实际示例是Task<T>.NET中的类型,它Task<U> ContinueWith<U>(Func<Task<T>, U>)bind(或SelectMany在C#中称为)的对偶。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.