Récemment, j'ai épousseté mes connaissances sur le fonctionnement des Monades. J'ai également été initié au concept d'un 'Comonad' , qui est décrit comme le inverse double d'une monade . Cependant, je suis impossible d'envelopper ma tête autour d'elle.
Pour comprendre les Monades, je me suis fait l'analogie:
Les monades peuvent être considérées comme "un modèle pour construire des bandes transporteuses d'expressions".
Pour définir une nouvelle Monade (un nouveau type de système de convoyeur à bande), vous devez définir:
- Un moyen de mettre quelque chose sur un tapis roulant, par ex. "démarrer" un tapis roulant. (Connu sous le nom de
unit
oureturn
)- Un moyen de connecter une machine (une expression) qui fera partie d'un tapis roulant à un tapis roulant. (Connu sous le nom de
join
oubind
ou>>=
).(Il y a une troisième opération qui prend le tapis roulant actuel, jette son contenu et démarre un nouveau tapis roulant appelé
>>
, mais il est très rarement utilisé.)Pour que les machines et les convoyeurs fonctionnent correctement ensemble, vous devez vous assurer que:
- Si vous placez quelque chose sur un tapis roulant et le passez dans une machine, la sortie doit être la même que lorsque vous la passez manuellement dans la machine. (Identité gauche)
- Si vous voulez placer une bande transporteuse entre une bande transporteuse déjà existante, vous ne devriez pas vous retrouver avec une bande transporteuse qui a une bande transporteuse sur le dessus, mais plutôt une bande transporteuse unique et plus longue. (Identité correcte)
- Cela ne devrait pas avoir d'importance pour la sortie si vous utilisez manuellement la machine A, puis passez le résultat via le BC connecté au convoyeur, ou si vous utilisez AB connecté au convoyeur et passez ensuite le résultat manuellement via C.En d'autres termes: ((a >> = b) >> = c) doit être identique à (a >> = (b >> = c)) (Associativité)
La bande transporteuse la plus simple serait celle qui prend simplement l'entrée et continue toujours à l'expression suivante. Voilà ce qu'est un "pipeline".
Une autre possibilité consiste à ne le laisser passer par la machine suivante que si une condition est remplie pour la valeur. Cela signifie que si au niveau de certaines expressions intermédiaires, la valeur devient quelque chose qui n'est plus autorisé, le reste des expressions sera ignoré. C'est ce que fait la monade "Peut-être" à Haskell.
Vous pouvez également effectuer d'autres règles de copie/modification conditionnelles de fantaisie sur les valeurs avant ou après leur transmission à une machine. Un exemple: analyseurs (ici, si une expression renvoie un résultat "échec", la valeur de avant l'expression est utilisée en sortie).
Bien sûr, l'analogie n'est pas parfaite, mais j'espère qu'elle donne une bonne représentation du fonctionnement des monades.
Cependant, j'ai beaucoup de mal à renverser cette analogie pour comprendre les Comonads. Je sais d'après les petites quantités d'informations que j'ai trouvées sur Internet qu'un Comonad définit:
extract
, qui est en quelque sorte l'inverse de return
, c'est-à-dire qu'il prend une valeur d'une Comonad .duplicate
, qui est en quelque sorte l'inverse de join
, c'est-à-dire qu'il crée deux Comonads à partir d'une seule.Mais comment une Comonad peut-elle être instanciée si nous ne pouvons en extraire ou les dupliquer? Et comment peuvent-ils réellement être utilisés? J'ai vu ce projet très étonnant et le discours à ce sujet (que j'ai malheureusement très peu compris), mais je ne suis pas sûr de la partie de la fonctionnalité fournie par un Comonad exactement.
Qu'est-ce qu'une Comonad? À quoi servent-ils? Comment peuvent-ils être utilisés? Sont-ils comestibles?
Une comonade est, tout comme une monade, une structure mathématique dans la théorie des catégories. Le co-préfixe y est très courant pour désigner les "inverses" comme vous le dites (bien que je ne pense pas que les mathématiciens purs soient d'accord sur le choix de Word).
Dans la théorie des catégories, il y a categories
, qui sont brièvement mis une collection de objects
(de tout type ou nature, la structure interne n'est pas pertinente) et quelques arrows
entre ces objets. Pour que quelque chose soit une catégorie, les flèches doivent suivre certaines lois (identité gauche/droite et associativité), mais ce n'est pas vraiment important ici.
Maintenant, la théorie des catégories est à la fois très abstraite/difficile à comprendre et vaste. Il faut beaucoup de temps pour passer par tout cela (et je ne l'ai pas étudié formellement, je ne connais que quelques notions de base), mais il existe une notion utilisée qui s'appelle un dual
. Fondamentalement, pour chaque catégorie, vous pouvez construire un opposite category
En faisant simplement la même chose mais en "inversant toutes les flèches". Il s'agit d'une définition très naïve, mais il est difficile d'essayer de résumer. Le double de quelque chose dans une catégorie C est fondamentalement la même chose dans la catégorie opposée C_op (vous avez encore mal à la tête?)
Quoi qu'il en soit, si vous avez une monade sur une catégorie (et une catégorie peut par exemple être une catégorie où les objets sont des types dans un langage de programmation et les flèches sont des fonctions entre les types), alors une comonad est fondamentalement la même chose, seulement vous 'ai inversé toutes les flèches (un peu comme inverser les signatures de fonction dans ce cas).
Une description plus "concrète" (mais pas SUPER pratique) peut être trouvée dans cette discussion entre Erik Meijer et Brian Beckman où ils discutent de la notion de dualité et comment Erik a fait pour "inverser" les flèches "pour IEnumerable<T>
en C # lors de la création du framework réactif et IObservable<T>
(qui pour autant que je sache, et je suis heureux d'être corrigé, est fondamentalement une instance de liste comonad).
Un autre exemple pratique de comonads mentionné dans la vidéo est le type Task<T>
Dans .NET, où Task<U> ContinueWith<U>(Func<Task<T>, U>)
serait le double de bind
(ou SelectMany
as ça s'appelle en C #)
De ma petite compréhension, une comonad est une machine Rube Goldberg pour faire des post-docs:
http://www.willamette.edu/~fruehr/haskell/evolution.html
... désolé, je n'ai pas pu y résister.