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:
- Uma maneira de colocar algo em uma correia transportadora, por exemplo, 'iniciar' uma correia transportadora. (Conhecido como
unit
oureturn
)- Uma maneira de conectar uma máquina (uma expressão) que fará parte de uma correia transportadora a uma correia transportadora. (Conhecido como
join
oubind
ou>>=
).(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:
- 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)
- 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)
- 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 reversoreturn
, ou seja, ele tem um valor fora de um Comonad.duplicate
, que é o inverso dejoin
, 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?
IO
mônada é o sistema de tempo de execução Haskell, que invocamain
. Há tambémunsafePerformIO
, é claro. Se você quiser pensar naMaybe
mônada como tendo uma "máquina no final da correia transportadora", poderá usarmaybe
.cobind
aplicativos, deve haver alguma função que faça algo útil na representação interna de sua comonada.Respostas:
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çãoobjects
(de qualquer tipo ou natureza, a estrutura interna é irrelevante) e algunsarrows
entre 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 umopposite category
fazendo 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 eIObservable<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, ondeTask<U> ContinueWith<U>(Func<Task<T>, U>)
seria o duplo debind
(ouSelectMany
como é chamado em C #)fonte
Do meu entendimento, uma comonada é uma máquina Rube Goldberg para fazer pós-documentos:
http://www.willamette.edu/~fruehr/haskell/evolution.html
... desculpe, eu não pude resistir.
fonte