Quels problèmes de programmation les monades résolvent-elles? [fermé]

14

J'ai lu beaucoup de messages qui expliquent ce que sont les monades, comment unitet bindfonctionnent, certains plongeant directement dans la théorie des catégories si abstraite (pour moi au moins) qui fait saigner les yeux, certains l'ignorant complètement et touchant à des analogies étranges de burritos, boîtes et autres.

Après quelques semaines d'étude et beaucoup de neurones frits, (je pense) je comprends comment fonctionnent les Monades. Mais il y a encore une chose qui échappe à ma compréhension, quelque chose que peu de messages abordent (sauf pour les entrées-sorties et l'état):

POURQUOI?

Pourquoi les monades sont-elles importantes? Pourquoi sont-ils si importants? Quels sont les problèmes qu'ils résolvent? Ces problèmes peuvent-ils être résolus uniquement avec les Monades ou existe-t-il d'autres moyens?

Dummy Me
la source
3
Les programmes sont grands et complexes. Nous avons besoin de moyens pour les structurer. Il y a plusieurs façons. Les monades ne font qu'un. Les flèches sont un. Les foncteurs ne font qu'un. Les objets, les classes, les fonctions, les méthodes, les modules, les traits, les mixins, les packages, sont quelques autres, ce n'est vraiment pas clair quelle est votre question spécifique. Demandez-vous pourquoi nous devons structurer les programmes?
Jörg W Mittag
1
@ JörgWMittag: Je ne demande PAS pourquoi nous devons structurer les programmes. Évidemment, un gros problème est divisé en plus petits que vous pouvez résoudre et ensuite combiner pour obtenir la solution du plus gros. Je demande quels problèmes les Monades résolvent. Est-ce que c'est ça? Code de structuration? Est-ce que c'est tout ce bruit? Par exemple, dans Haskell, c'est ainsi que vous effectuez les E / S. Là, la monade est une pièce de théâtre faisant semblant d'agir comme quelque chose de pur alors qu'elle ne l'est pas. Ma question est dans le titre, je ne sais pas comment le dire plus clairement.
Dummy Me
2
Pourquoi des monades?
Robert Harvey
1
@RobertHarvey: J'ai également trouvé les deux premiers liens que vous avez ajoutés, mais comme dans les réponses de ces messages et d'autres, les réponses vont directement à peut-être, State et IO monads, sautant rapidement aux exemples ou au code, et se terminant par "il y a beaucoup des problèmes qui peuvent être résolus en utilisant Monads ". Quels sont les autres types de problèmes? Je cherche une réponse de niveau supérieur qui, au lieu de réitérer les mêmes exemples, va à la racine des problèmes (quels qu'ils soient) et explique comment les monades les résolvent et pourquoi c'est le meilleur choix, par opposition à utiliser autre chose. Merci beaucoup pour vos commentaires.
Dummy Me

Réponses:

10

Vous n'avez pas besoin de monades pour résoudre quoi que ce soit. Ils rendent simplement certaines choses plus simples. Beaucoup de gens deviennent trop abstraits et théoriques pour expliquer les monades. La plupart du temps, les monades sont un modèle qui revient sans cesse dans la programmation. En reconnaissant ce modèle, nous pouvons simplifier notre code et éviter de réimplémenter certaines fonctions.

Pour Haskell, d'un point de vue concret, la chose la plus visible permise par les monades est la notation . La compréhension des listes en Haskell et dans d'autres langues profite également largement des monades. Vous pouvez également créer des bibliothèques comme Control.Monad .

Tous ces éléments fournissent des simplifications utiles, et une fois que vous l'avez implémenté pour une monade, vous l'obtenez automatiquement pour toutes les monades. C'est l'une des principales raisons pour lesquelles la réutilisation du code est tellement plus facile pour la programmation fonctionnelle que les autres paradigmes.

Karl Bielefeldt
la source
2
Je dirais en fait que la chose la plus visible que les monades haskell activent est un moyen facile d'avoir des effets d'E / S qui fonctionnent réellement comme vous vous y attendez. Je pense que quiconque se demande ce que nous donnent les monades devrait essayer Miranda . Miranda est la langue que Haskell a été conçue pour remplacer, et devrait être très facile à apprendre pour toute personne ayant une expérience Haskell. La principale différence est qu'il n'a pas d'E / S monadiques, ce qui rend le langage beaucoup plus difficile à utiliser que Haskell pour tout projet non trivial.
Jules
Oui, IOc'est la monade la plus en vue de Haskell , mais je ne listais pas d'exemples de monades individuelles. Je listais des exemples des abstractions globales qu'ils permettent. J'essayais de comprendre pourquoi, par exemple, le premier gars à penser à utiliser une monade pour IO penserait que c'est une bonne idée en général.
Karl Bielefeldt
1
@Jules: Ou regardez l'histoire de Haskell. Avant Monads, les concepteurs Haskell ont expérimenté avec Lazy Streams et Continuations comme base d'E / S, et les deux étaient difficiles à utiliser.
Jörg W Mittag
5

Il est plus facile à comprendre si vous regardez les monades particulières et voyez quels problèmes elles résolvent. Par exemple, à Haskell:

  • IO: Permet à IO d'être représenté dans le système de type, de sorte que vous pouvez clairement séparer les fonctions pures des fonctions exécutant les IO.

  • Liste: permet d'effectuer des compréhensions de listes et des calculs nodéterministes.

  • Peut-être: une meilleure alternative aux nulls, et supportant quelque chose de comparable à l'opérateur de coalescence nulle de C #.

  • Parsec: DSL pratique pour écrire des analyseurs.

Il est donc facile (j'espère) de voir la justification des différentes monades, car elles sont toutes assez utiles. Mais les problèmes qu'ils résolvent sont également très différents et, à première vue, ils ne semblent pas avoir grand-chose en commun, sauf qu'ils sont tous liés à une logique de chaînage des opérations. Les monades sont utiles car elles vous permettent de créer une telle variété d'outils.

Les exemples ci-dessus pourraient-ils être mis en œuvre sans monades? Certes, ils pourraient être implémentés de manière ad hoc, mais le fait d'avoir des monades intégrées dans le langage permet un support direct de la langue comme la do-notation qui fonctionne avec toutes les monades.

JacquesB
la source
2

Une chose qui le rend déroutant est que les fonctions "populaires" aiment bindet <*>sont orientées vers la pratique. Mais pour comprendre les concepts, il est plus facile d'examiner d'abord les autres fonctions. Il convient également de noter que les monades se démarquent car elles sont un peu sur-typées par rapport aux autres concepts connectés. Je vais donc commencer par les foncteurs à la place.

Les foncteurs proposent une fonction (en notation Haskell) fmap :: (Functor f) => (a -> b) -> f a -> f b. En d'autres termes, vous disposez d'un contexte dans flequel vous pouvez intégrer une fonction. Comme vous pouvez l'imaginer, presque tout est un foncteur. Listes, Peut-être, Soit, fonctions, E / S, tuples, analyseurs ... Chacun représente un contexte dans lequel une valeur peut apparaître. Vous pouvez donc écrire des fonctions extrêmement polyvalentes qui fonctionnent dans presque tous les contextes en utilisant fmapou sa variante en ligne <$>.

Quelles autres choses voulez-vous faire avec les contextes? Vous voudrez peut-être combiner deux contextes. Donc , vous voudrez peut - être obtenir une généralisation de zip :: [a] -> [b] -> [(a,b)]par exemple comme ceci: pair :: (Monoidal f) => f a -> f b -> f (a,b).

Mais parce que c'est encore plus utile dans la pratique, les bibliothèques Haskell proposent à la place Applicative, qui est une combinaison de Functoret Monoidal, Et aussi de Unit, qui ajoute simplement que vous pouvez réellement mettre des valeurs "à l'intérieur" de votre contexte avec unit.

Vous pouvez écrire des fonctions extrêmement génériques en déclarant simplement ces trois choses sur le contexte dans lequel vous travaillez.

Monadest juste une autre chose que vous pouvez dire en plus de cela. Ce que je n'ai pas mentionné auparavant, c'est que vous avez déjà deux façons de combiner deux contextes: vous pouvez non seulement pairles utiliser, mais vous pouvez également les empiler, par exemple, vous pouvez avoir une liste de listes. Dans le contexte d'E / S, un exemple serait une action d'E / S qui peut lire d'autres actions d'E / S à partir d'un fichier, vous auriez donc un type FilePath -> IO (IO a). Comment pouvons-nous nous débarrasser de cet empilement pour obtenir une fonction exécutable IO a? C'est là Monadqu'intervient s join, il nous permet de combiner deux contextes empilés du même type. Il en va de même pour les analyseurs, Peut-être etc. Et bindest juste un moyen plus pratique d'utiliserjoin

Un contexte monadique n'a donc qu'à offrir quatre choses et il peut être utilisé avec presque toutes les machines développées pour les E / S, les analyseurs, les pannes, etc.

MarLinn
la source
1

Monads vous permet d'exprimer divers calculs non purs ainsi que de simplifier le code

  • calcul avec état (get / set state via monad)
  • E / S (journalisation, interface utilisateur, fichier ou simplement produire / consommer une liste de X)
  • Aussi, flux de contrôle "non linéaire" (c.-à-d. Exceptions, peut-être, etc.)

Et, surtout sans compromettre les constructions de langage pur et en tirer un langage plus propre

Macke
la source
2
C'est vrai - mais ce n'est qu'une partie de l'utilisation des monades. Énumérez les compréhensions ou Maybene sont pas liées à quelque chose d'extérieur.
JacquesB
Il serait utile que les downvoteurs expliquent pourquoi ils l'ont fait. Je ne vois rien de mal à cette réponse.
Jules
@JacquesB, ils sont cependant avec état.
Jules
1
Les types de monde, les types d'unicité, les types linéaires vous permettent également de le faire.
Jörg W Mittag
@Jules Lists comme une monade non déterministe est avec état? Pourriez-vous préciser quelle est votre définition de «avec état»?
Jack