O que é uma Comonad e como eles são úteis?

16

Recentemente, venho divulgando meu conhecimento sobre como as mônadas funcionam. Também fui apresentado ao conceito de 'Comonad' , descrito como o dual inverso de uma mônada . No entanto, sou impossível envolvê-lo.

Para entender as Mônadas, fiz a própria analogia:

Mônadas podem ser vistas como "um plano para construir correias transportadoras de expressões".

Para definir um novo Monad (um novo tipo de sistema de correia transportadora), é necessário definir:

  1. Uma maneira de colocar algo em uma correia transportadora, por exemplo, 'iniciar' uma correia transportadora. (Conhecido como unitou return)
  2. Uma maneira de conectar uma máquina (uma expressão) que fará parte de uma correia transportadora a uma correia transportadora. (Conhecido como joinou bindou >>=).

(Existe uma terceira operação que pega a correia transportadora atual, joga seu conteúdo fora e inicia uma nova correia transportadora conhecida como >>, mas é usada muito raramente.)

Para que as máquinas e os transportadores funcionem corretamente juntos, você precisará garantir que:

  1. Se você colocar algo em uma correia transportadora e passá-lo através de uma máquina, a saída deve ser a mesma de quando você passa manualmente pela máquina. (Identidade Esquerda)
  2. Se você deseja colocar uma correia transportadora entre uma correia transportadora já existente, não deve acabar com uma correia transportadora que tenha uma correia transportadora no topo, mas sim uma correia transportadora única e mais longa. (Identidade correta)
  3. Não deve importar para a saída se você usar manualmente a máquina A e depois passar o resultado pelo BC conectado ao transportador, ou se você usar o AB conectado ao transportador e depois passar o resultado manualmente através de C. Em outras palavras: ((a >> = b) >> = c) deve ser o mesmo que (a >> = (b >> = c)) (Associatividade)

A correia transportadora mais simples seria aquela que apenas recebe a entrada e continua sempre na próxima expressão. Isto é o que é um "pipeline".

Outra possibilidade é deixá-lo passar pela próxima máquina se alguma condição for atendida para o valor. Isso significa que, se em algumas expressões intermediárias o valor mudar para algo que não é mais permitido, o restante das expressões será ignorado. É isso que a mônada 'Talvez' faz em Haskell.

Você também pode executar outras regras de cópia / alteração condicionais sofisticadas nos valores antes ou depois de passá-las para uma máquina. Um exemplo: Analisadores (Aqui, se uma expressão retornar um resultado de 'falha', o valor anterior à expressão será usado como saída).

Claro que a analogia não é perfeita, mas espero que dê uma boa representação de como as mônadas funcionam.

No entanto, estou tendo muitos problemas para mudar essa analogia para entender as Comonadas. Sei pelas pequenas quantidades de informações que encontrei na internet que uma Comonad define:

  • extract, Que é uma espécie de reverso return, ou seja, ele tem um valor fora de um Comonad.
  • duplicate, que é o inverso de join, ou seja, cria duas comonadas a partir de uma única.

Mas como uma Comonad pode ser instanciada se somos capazes de extraí-las ou duplicá-las? E como eles podem realmente ser usados? Eu já vi esse projeto incrível e a conversa sobre ele (do qual, infelizmente, compreendi muito pouco), mas não tenho certeza de que parte da funcionalidade é fornecida exatamente por uma Comonad.

O que é uma Comonad? Para que eles são úteis? Como eles podem ser usados? Eles são comestíveis?

Qqwy
fonte
2
"como uma Comonad pode ser instanciada se somos capazes de extraí-las ou duplicá-las?" - Responderei à sua pergunta com uma pergunta: como uma Mônada pode ser consumida se você só consegue elevar valores neles e sequenciar os cálculos?
Benjamin Hodgson
1
A "máquina no final da correia transportadora" (aparte: não acho analogias tão úteis quando se fala de mônadas) da IOmônada é o sistema de tempo de execução Haskell, que invoca main. Há também unsafePerformIO, é claro. Se você quiser pensar na Maybemônada como tendo uma "máquina no final da correia transportadora", poderá usar maybe.
Benjamin Hodgson
1
Mas, mudando sua explicação, quando você deseja produzir um valor comonádico no início de uma cadeia de cobindaplicativos, deve haver alguma função que faça algo útil na representação interna de sua comonada.
Benjamin Hodgson
2
Uma instância específica de comonad ou monad pode claramente ter mais funcionalidade do que o necessário apenas para implementar as classes de tipos
jk.
2
Não que isso seja útil, se você não abordar essa questão do lado teórico / matemático da categoria, mas eu queria salientar que uma comonada não é a inversa, mas o dual de uma mônada.
Jörg W Mittag

Respostas:

11

Uma comonada é, assim como uma mônada, uma estrutura matemática na teoria das categorias. O co-prefixo é muito comum lá para denotar "inversos" como você diz (embora eu não ache que matemáticos puros concordam com a escolha da palavra).

Na teoria das categorias existem categories, os quais são brevemente colocados em uma coleção objects(de qualquer tipo ou natureza, a estrutura interna é irrelevante) e alguns arrowsentre esses objetos. Para que algo seja uma categoria, as setas devem seguir algumas leis (identidade esquerda / direita e associatividade), mas isso não é realmente importante aqui.

Agora, a teoria das categorias é muito abstrata / difícil de entender e vasta. Demora muito tempo para analisar tudo (e eu não o estudei formalmente, só sei algumas noções básicas), mas existe uma noção usada chamada a dual. Basicamente, para cada categoria, você pode construir um opposite categoryfazendo a mesma coisa, mas "invertendo todas as setas". Essa é uma definição muito ingênua, mas é difícil tentar resumir. O dual de algo em uma categoria C é basicamente a mesma coisa na categoria oposta C_op (já está com dor de cabeça?)

De qualquer forma, se você tem uma mônada sobre alguma categoria (e uma categoria pode, por exemplo, ser uma categoria em que os objetos são tipos em alguma linguagem de programação e as setas são funções entre os tipos), uma comonada é basicamente a mesma coisa, somente você inverteu todas as setas (como reverter as assinaturas de função neste caso).

Uma descrição mais "prática" (embora não SUPER prática) pode ser encontrada nesta discussão entre Erik Meijer e Brian Beckman, onde estão discutindo a noção de dualidade e como Erik "revirou as flechas" IEnumerable<T>em C # quando criando a estrutura reativa e IObservable<T>(que, até onde eu sei, e estou feliz em ser corrigida, basicamente é uma instância de lista comum).

Outro exemplo prático de comônadas mencionadas no vídeo é o Task<T>tipo .NET, onde Task<U> ContinueWith<U>(Func<Task<T>, U>)seria o duplo de bind(ou SelectManycomo é chamado em C #)

sara
fonte