Première: Le terme monade est un peu vide de sens si vous n'êtes pas un mathématicien. Un autre terme est le calcul du générateur qui est un peu plus descriptif de ce qu'ils sont réellement utiles.
Vous demandez des exemples pratiques:
Exemple 1: compréhension de Liste:
[x*2 | x<-[1..10], odd x]
Cette expression renvoie le double de tous les nombres impairs dans la gamme de 1 à 10. Très utile!
Il s'avère que c'est vraiment juste sucre syntaxique pour certaines opérations au sein de la Liste monade. La même compréhension de liste peut être écrite comme:
do
x <- [1..10]
if odd x
then [x * 2]
else []
Ou encore:
[1..10] >>= (\x -> if odd x then [x*2] else [])
Exemple 2: Entrée/Sortie:
do
putStrLn "What is your name?"
name <- getLine
putStrLn ("Welcome, " ++ name ++ "!")
Les deux exemples utilise des monades, aka le calcul des constructeurs. Le thème commun est que la monade des chaînes d'opérations dans certains spécifiques, de façon utile. Dans la compréhension de liste, les opérations sont enchaînés de telle sorte que si une opération retourne une liste, puis les opérations suivantes sont effectuées sur chaque élément dans la liste. Le IO monade sur l'autre main effectue les opérations de façon séquentielle, mais passe une "variable cachée", qui représente "l'état du monde", ce qui nous permet d'écrire IO code dans un pur manière fonctionnelle.
Il s'avère que le modèle de chaînage des opérations est très utile, et est utilisé pour beaucoup de choses différentes en Haskell.
Un autre exemple est des exceptions: à l'Aide de l' Error
monade, les opérations sont enchaînés, telles qu'elles sont effectuées de manière séquentielle, sauf si une erreur est levée, auquel cas le reste de la chaîne est à l'abandon.
À la fois la liste-de la compréhension de la syntaxe et de la notation sont sucre syntaxique pour le chaînage des opérations à l'aide de l' >>=
de l'opérateur. Une monade est fondamentalement juste un type qui prend en charge l' >>=
de l'opérateur.
Exemple 3: Un analyseur
C'est très simple analyseur qui analyse une chaîne ou un nombre:
parseExpr = parseString <|> parseNumber
parseString = do
char '"'
x <- many (noneOf "\"")
char '"'
return (StringValue x)
parseNumber = do
num <- many1 digit
return (NumberValue (read num))
Les opérations d' char
, digit
etc. sont assez simples, ils correspondent ou ne correspondent pas. La magie est la monade qui gère le contrôle de flux: Les opérations sont effectuées de manière séquentielle jusqu'à une correspondance échoue, auquel cas la monade revient à la dernière <|>
et tente l'option suivante. De nouveau, une sorte de chaînage des opérations avec certains autres, utiles à la sémantique.
Exemple 4: la programmation Asynchrone
Les exemples ci-dessus sont en Haskell, mais il s'avère F# prend également en charge les monades. Cet exemple est volé de Don Syme:
let AsyncHttp(url:string) =
async { let req = WebRequest.Create(url)
let! rsp = req.GetResponseAsync()
use stream = rsp.GetResponseStream()
use reader = new System.IO.StreamReader(stream)
return reader.ReadToEnd() }
Cette méthode extrait d'une page web. Le punch line est l'utilisation de l' GetResponseAsync
- il réellement attend la réponse sur un autre fil, tandis que le thread principal renvoie à partir de la fonction. Les trois dernières lignes sont exécutées sur le pondu fil lorsque la réponse n'a été reçue.
Dans la plupart des autres langues, vous devez créer explicitement une fonction distincte pour les lignes qui gèrent la réponse. L' async
monade est capable de "diviser" le bloc sur son propre et surseoir à l'exécution de la seconde moitié. ( async {}
De la syntaxe indique que le flux de contrôle dans le bloc est défini par l' async
monade)
Comment ils fonctionnent
Alors, comment pouvez-monade faire toutes ces fantaisie de contrôle des flux de chose? Ce qui se passe réellement dans un bloc (ou un calcul de l'expression , comme on les appelle en F#), c'est que chaque opération (en gros à chaque ligne) est enveloppé dans une autre fonction anonyme. Ces fonctions sont ensuite combinées à l'aide de l' bind
opérateur (orthographié >>=
en Haskell). Depuis l' bind
opération combine les fonctions, il peut les exécuter comme il l'entend: de manière séquentielle, à plusieurs reprises, dans le sens inverse, ignorer certains, exécuter certaines sur un thread séparé quand il se sent comme il et ainsi de suite.
Comme un exemple, c'est la version étendue de l'OI-code de l'exemple 2:
putStrLn "What is your name?"
>>= (\_ -> getLine)
>>= (\name -> putStrLn ("Welcome, " ++ name ++ "!"))
C'est la plus laide, mais c'est aussi plus évident que ce qui se passe réellement. L' >>=
de l'opérateur est l'ingrédient magique: Elle prend une valeur (sur la gauche) et les combine avec une fonction (sur le côté droit), pour produire une nouvelle valeur. Cette nouvelle valeur est alors prise par le prochain >>=
de l'opérateur et de nouveau combiné avec une fonction pour produire une nouvelle valeur. >>=
peut être considéré comme un mini-évaluateur.
Notez que >>=
est surchargé pour les différents types, de sorte que chaque monade a sa propre implémentation d' >>=
. (Toutes les opérations de la chaîne doivent être du type de la même monade bien, sinon l' >>=
opérateur ne fonctionnent pas.)
La plus simple possible la mise en œuvre de l' >>=
seulement prend de la valeur sur la gauche et l'applique à la fonction sur la droite et renvoie le résultat, mais comme dit avant, ce qui rend l'ensemble du motif est utile quand il y a quelque chose de plus qui se passe dans la monade de mise en œuvre de l' >>=
.
Il y a plus d'intelligence dans la façon dont les valeurs sont transmises d'une opération à l'autre, mais cela nécessite une explication plus approfondie de la Haskell type de système.
Résumé
En Haskell-conditions une monade est un type paramétré, qui est une instance de la Monade type de classe, qui définit >>= avec quelques autres opérateurs. En d'autres termes, une monade est juste un type pour lequel l' >>=
y est défini.
En soi, >>=
est juste lourd sorte d'enchaînement de fonctions, mais avec la présence de la notation qui cache la "plomberie", le monadique des opérations s'avère être une très belle et utile, abstraction, utiles à plusieurs endroits dans la langue, et utile pour créer votre propre mini-langues dans la langue.
Pourquoi sont les monades dur?
Pour de nombreux Haskell-apprenants, les monades sont un obstacle ils ont frappé comme un mur de briques. Ce n'est pas que les monades sont eux-mêmes complexes, mais que la mise en œuvre s'appuie sur de nombreuses autres avancées Haskell caractéristiques comme le type paramétré, les classes de type, et ainsi de suite. Le problème est que Haskell IO est basé sur des monades, et IO est probablement l'une des premières choses que vous voulez comprendre lors de l'apprentissage d'une nouvelle langue - après tout, ce n'est pas beaucoup de plaisir à créer des programmes qui ne produisent pas de sortie. Je n'ai pas de solution immédiate pour ce dilemme de la poule et de l'oeuf problème, sauf le traitement des IO comme "la magie qui se passe ici" jusqu'à ce que vous avez assez d'expérience avec d'autres parties de la langue. Désolé.
12 votes
Eric Lippert a écrit une réponse à ces questions (stackoverflow.com/questions/2704652/…), qui est due à certaines questions vivent sur une page séparée.
72 votes
Voici une nouvelle introduction utilisant du javascript - Je l'ai trouvé très lisible.
7 votes
Voir aussi Différentes façons de voir un monade.
25 votes
Voir aussi Monades en images
3 votes
Un monade est un tableau de fonctions avec des opérations auxiliaires. Voir cette réponse
0 votes
Un autre article rapide qui ressemble à la réponse de sigfpe : github.com/quchen/articles/blob/master/…
0 votes
Voir mon article FPComplete sur le POURQUOI vous voudriez utiliser des monades (pas comment elles fonctionnent) : bit.ly/MH9zRD
2 votes
La meilleure explication que j'ai entendue jusqu'à présent vient en fait de Wikipédia ; "Les monades sont des points-virgules programmables."
0 votes
Je suis tombé sur cet article: stephanboyer.com/post/9/monads-part-1-a-design-pattern. Je l'ai trouvé être la meilleure et la plus efficace explication conceptuelle pour les non-initiés comme moi jusqu'à présent. L'auteur a en réalité d'autres articles sur les monades également.
0 votes
Une explication extrêmement facile à suivre par Douglas Crockford : youtube.com/watch?v=dkZFtimgAcM
0 votes
Monad n'est pas un concept spécifique à Haskell, @HelderPereira. Votre retag semble incorrect à mes yeux.
1 votes
@Palec Je sais, mais la question mentionne Haskell et la réponse la plus votée utilise Haskell pour l'expliquer. J'ai juste pensé que ce serait utile de le faciliter pour les personnes qui apprennent Haskell de le trouver, car c'est un concept très important du langage. Vous êtes libre cependant de le supprimer, si vous pensez que cela n'a pas de sens.
0 votes
J'aime dire que la monade est une construction qui vous permet de mettre toutes vos bêtises dedans (faire le vrai travail, alias les effets secondaires), et de vous présenter une boîte fantaisie pour garder votre code fonctionnel (lire sans effets secondaires).
0 votes
Monad est un EDSL. Voir ceci: "Quelqu'un à un certain moment a remarqué, "oh, pour obtenir des effets impurs à partir de code pur, j'ai besoin de faire de la méta-programmation, ce qui signifie qu'un de mes types doit être 'des programmes qui calculent un X'. Je veux prendre un 'programme qui calcule un X' et une fonction qui prend un X et produit le prochain programme, un 'programme qui calcule un Y', et les coller ensemble pour obtenir un 'programme qui calcule un Y' " (qui est l'opération de liaison). Le monade IO est née."
0 votes
Cet article de Tomasz Nurkiewicz est la meilleure explication destinée aux développeurs Java que j'ai trouvée.
0 votes
Plus court: Monad est le pattern (embedded) Interpreter (où les instructions du langage étant interprété sont des valeurs de première classe de notre langage de programmation lui-même).
0 votes
Les monades sont des langages de domaine intégrés spécifiques qui ont des instructions (points-virgules). Les points-virgules pourraient représenter des instructions dans des langages procéduraux traditionnels, des jointures en SQL, ou ce que vous voulez. Comme vous pouvez fusionner des monades pour créer des langages avec une sémantique plus riche, ou diviser des monades, vous pouvez aussi considérer les monades comme étant la SÉMANTIQUE des langages eux-mêmes.