Je viens d'un milieu C #, où LINQ a évolué en Rx.NET, mais a toujours eu un certain intérêt pour FP. Après une introduction aux monades et quelques projets parallèles en F #, j'étais prêt à essayer de passer au niveau suivant.
Maintenant, après plusieurs discussions sur la monade gratuite de personnes de Scala et plusieurs écritures en Haskell, ou F #, j'ai trouvé des grammaires avec des interprètes pour que la compréhension soit assez similaire aux IObservable
chaînes.
Dans FRP, vous composez une définition d'opération à partir de blocs spécifiques à un domaine plus petit, y compris les effets secondaires et les échecs qui restent à l'intérieur de la chaîne, et modélisez votre application comme un ensemble d'opérations et d'effets secondaires. En monade libre, si j'ai bien compris, vous faites de même en faisant vos opérations en tant que foncteurs, et en les soulevant à l'aide de coyoneda.
Quelles seraient les différences entre les deux qui inclinent l'aiguille vers l'une des approches? Quelle est la différence fondamentale lors de la définition de votre service ou programme?
la source
Cont
c'est la seule monade que j'ai vue suggérer qui ne peut pas être exprimée via la monade libre, on peut probablement supposer que FRP peut l'être. Comme presque tout le reste .IObservable
est une instance de la monade de continuation.Réponses:
Monades
Une monade se compose de
Un endofuncteur . Dans notre monde du génie logiciel, nous pouvons dire que cela correspond à un type de données avec un seul paramètre de type sans restriction. En C #, ce serait quelque chose de la forme:
Deux opérations définies sur ce type de données:
return
/pure
prend une valeur "pure" (c'est-à-dire uneT
valeur) et "l'enveloppe" dans la monade (c'est-à-dire qu'elle produit uneM<T>
valeur). Puisquereturn
c'est un mot-clé réservé en C #, je vais utiliserpure
pour faire référence à cette opération à partir de maintenant. En C #,pure
serait une méthode avec une signature comme:bind
/flatmap
prend une valeur monadique (M<A>
) et une fonctionf
.f
prend une valeur pure et retourne une valeur monadique (M<B>
). À partir de ceux-ci,bind
produit une nouvelle valeur monadique (M<B>
).bind
a la signature C # suivante:En outre, pour être une monade,
pure
etbind
sont tenus d'obéir aux trois lois de la monade.Maintenant, une façon de modéliser des monades en C # serait de construire une interface:
(Remarque: afin de garder les choses brèves et expressives, je vais prendre quelques libertés avec le code tout au long de cette réponse.)
Nous pouvons maintenant implémenter des monades pour des types de données concrets en implémentant des implémentations concrètes de
Monad<M>
. Par exemple, nous pouvons implémenter la monade suivante pourIEnumerable
:(J'utilise délibérément la syntaxe LINQ pour appeler la relation entre la syntaxe LINQ et les monades. Mais notez que nous pourrions remplacer la requête LINQ par un appel à
SelectMany
.)Maintenant, pouvons-nous définir une monade pour
IObservable
? Il semblerait donc:Pour être sûr que nous avons une monade, nous devons prouver les lois de la monade. Cela peut être non trivial (et je ne connais pas suffisamment Rx.NET pour savoir s'ils peuvent même être prouvés à partir de la seule spécification), mais c'est un début prometteur. Pour faciliter le reste de cette discussion, supposons simplement que les lois de la monade s'appliquent dans ce cas.
Monades gratuites
Il n'y a pas de "monade libre" singulière. Les monades libres sont plutôt une classe de monades construites à partir de foncteurs. Autrement dit, étant donné un foncteur
F
, nous pouvons automatiquement dériver une monade pourF
(c'est-à-dire la monade libre deF
).Foncteurs
Comme les monades, les foncteurs peuvent être définis par les trois éléments suivants:
Deux opérations:
pure
encapsule une valeur pure dans le foncteur. Ceci est analogue àpure
une monade. En fait, pour les foncteurs qui sont aussi des monades, les deux doivent être identiques.fmap
mappe les valeurs de l'entrée aux nouvelles valeurs de la sortie via une fonction donnée. Sa signature est:Comme les monades, les foncteurs sont tenus d'obéir aux lois des foncteurs.
Comme pour les monades, nous pouvons modéliser des foncteurs via l'interface suivante:
Maintenant, comme les monades sont une sous-classe de foncteurs, nous pourrions également refactoriser
Monad
un peu:Ici, j'ai ajouté une méthode supplémentaire
join
, et fourni des implémentations par défaut dejoin
etbind
. Notez cependant qu'il s'agit de définitions circulaires. Vous devez donc remplacer au moins l'un ou l'autre. Notez également qu'ilpure
est désormais hérité deFunctor
.IObservable
et monades gratuitesMaintenant, puisque nous avons défini une monade pour
IObservable
et puisque les monades sont une sous-classe de foncteurs, il s'ensuit que nous devons être en mesure de définir une instance de foncteur pourIObservable
. Voici une définition:Maintenant que nous avons défini un foncteur
IObservable
, nous pouvons construire une monade libre à partir de ce foncteur. Et c'est précisément ce qui seIObservable
rapporte aux monades libres - à savoir, que nous pouvons construire une monade libre à partir deIObservable
.la source