Diese Antwort beginnt mit einem motivierenden Beispiel, arbeitet das Beispiel durch, leitet ein Beispiel für eine Monade ab und definiert den Begriff "Monade" formal.
Betrachten Sie diese drei Funktionen in Pseudocode:
f(<x, messages>) := <x, messages "called f. ">
g(<x, messages>) := <x, messages "called g. ">
wrap(x) := <x, "">
f
nimmt ein geordnetes Paar der Form <x, messages>
und gibt ein geordnetes Paar zurück. Es lässt das erste Element unberührt und fügt "called f. "
zum zweiten Punkt. Dasselbe gilt für g
.
Sie können diese Funktionen zusammenstellen und erhalten Ihren ursprünglichen Wert zusammen mit einer Zeichenkette, die angibt, in welcher Reihenfolge die Funktionen aufgerufen wurden:
f(g(wrap(x)))
= f(g(<x, "">))
= f(<x, "called g. ">)
= <x, "called g. called f. ">
Ihnen missfällt die Tatsache, dass f
y g
sind für das Anhängen ihrer eigenen Protokollmeldungen an die vorherigen Protokollierungsinformationen verantwortlich. (Stellen Sie sich der Einfachheit halber vor, dass anstelle des Anhängens von Strings, f
y g
muss eine komplizierte Logik für das zweite Element des Paares ausführen. Es wäre mühsam, diese komplizierte Logik in zwei - oder mehr - verschiedenen Funktionen zu wiederholen).
Sie ziehen es vor, einfachere Funktionen zu schreiben:
f(x) := <x, "called f. ">
g(x) := <x, "called g. ">
wrap(x) := <x, "">
Aber sieh dir an, was passiert, wenn du sie komponierst:
f(g(wrap(x)))
= f(g(<x, "">))
= f(<<x, "">, "called g. ">)
= <<<x, "">, "called g. ">, "called f. ">
Das Problem ist, dass vorbei an ein Paar in eine Funktion umwandelt, erhält man nicht das, was man will. Aber was wäre, wenn Sie Futtermittel ein Paar in eine Funktion:
feed(f, feed(g, wrap(x)))
= feed(f, feed(g, <x, "">))
= feed(f, <x, "called g. ">)
= <x, "called g. called f. ">
Lesen Sie feed(f, m)
als "Futtermittel m
en f
". An Futtermittel ein Paar <x, messages>
in eine Funktion f
soll Pass x
en f
erhalten <y, message>
aus f
und zurück <y, messages message>
.
feed(f, <x, messages>) := let <y, message> = f(x)
in <y, messages message>
Beachten Sie, was passiert, wenn Sie drei Dinge mit Ihren Funktionen tun:
Erstens: Wenn Sie einen Wert einpacken und dann Futtermittel das resultierende Paar in eine Funktion:
feed(f, wrap(x))
= feed(f, <x, "">)
= let <y, message> = f(x)
in <y, "" message>
= let <y, message> = <x, "called f. ">
in <y, "" message>
= <x, "" "called f. ">
= <x, "called f. ">
= f(x)
Das ist dasselbe wie vorbei an den Wert in die Funktion.
Zweitens: Wenn Sie ein Paar in wrap
:
feed(wrap, <x, messages>)
= let <y, message> = wrap(x)
in <y, messages message>
= let <y, message> = <x, "">
in <y, messages message>
= <x, messages "">
= <x, messages>
Das ändert nichts an den beiden.
Drittens: Wenn Sie eine Funktion definieren, die x
und füttert g(x)
en f
:
h(x) := feed(f, g(x))
und füttern Sie sie mit einem Paar:
feed(h, <x, messages>)
= let <y, message> = h(x)
in <y, messages message>
= let <y, message> = feed(f, g(x))
in <y, messages message>
= let <y, message> = feed(f, <x, "called g. ">)
in <y, messages message>
= let <y, message> = let <z, msg> = f(x)
in <z, "called g. " msg>
in <y, messages message>
= let <y, message> = let <z, msg> = <x, "called f. ">
in <z, "called g. " msg>
in <y, messages message>
= let <y, message> = <x, "called g. " "called f. ">
in <y, messages message>
= <x, messages "called g. " "called f. ">
= feed(f, <x, messages "called g. ">)
= feed(f, feed(g, <x, messages>))
Das ist dasselbe wie die Eingabe des Paares in g
und Einspeisung des resultierenden Paares in f
.
Sie haben das meiste von einer Monade. Jetzt müssen Sie nur noch die Datentypen in Ihrem Programm kennen.
Welche Art von Wert ist <x, "called f. ">
? Nun, das hängt davon ab, welche Art von Wert x
ist. Wenn x
ist vom Typ t
dann ist Ihr Paar ein Wert vom Typ "Paar von t
und String". Nennen Sie diesen Typ M t
.
M
ist ein Typkonstruktor: M
allein verweist nicht auf einen Typ, sondern M _
bezieht sich auf einen Typ, sobald Sie das Feld mit einem Typ ausfüllen. Eine M int
ist ein Paar aus einem int und einer Zeichenkette. Eine M string
ist ein Paar aus einem String und einem String. Etc.
Glückwunsch, Sie haben eine Monade erstellt!
Formal ist Ihre Monade das Tupel <M, feed, wrap>
.
Eine Monade ist ein Tupel <M, feed, wrap>
où :
M
ist ein Typkonstruktor.
feed
nimmt eine (Funktion, die eine t
und gibt eine M u
) und ein M t
und gibt eine M u
.
wrap
nimmt eine v
und gibt eine M v
.
t
, u
y v
sind drei beliebige Typen, die gleich oder verschieden sein können. Eine Monade erfüllt die drei Eigenschaften, die Sie für Ihre spezifische Monade nachgewiesen haben:
-
Fütterung eine verpackte t
in eine Funktion ist dasselbe wie vorbei an die unverpackte t
in die Funktion.
Förmlich: feed(f, wrap(x)) = f(x)
-
Fütterung eines M t
en wrap
hat keine Auswirkungen auf die M t
.
Förmlich: feed(wrap, m) = m
-
Fütterung eines M t
(nennen Sie es m
) in eine Funktion, die
- geht die
t
en g
- erhält eine
M u
(nennen Sie es n
) von g
- Feeds
n
en f
ist dasselbe wie
- Fütterung
m
en g
- unter
n
de g
- Fütterung
n
en f
Förmlich: feed(h, m) = feed(f, feed(g, m))
wobei h(x) := feed(f, g(x))
Typischerweise, feed
heißt bind
(AKA >>=
in Haskell) und wrap
heißt return
.
13 Stimmen
Eric Lippert schrieb eine Antwort auf diese Fragen ( stackoverflow.com/questions/2704652/ ), die aufgrund einiger Probleme auf einer separaten Seite zu finden ist.
74 Stimmen
Hier ist eine neue Einführung in die Verwendung von Javascript - ich fand sie sehr lesenswert.
7 Stimmen
Siehe auch Verschiedene Arten, eine Monade zu sehen .
27 Stimmen
Siehe auch Monaden in Bildern
3 Stimmen
Eine Monade ist eine Reihe von Funktionen mit Hilfsoperationen. Siehe diese Antwort
0 Stimmen
Ein weiterer schneller Artikel, der der Antwort von sigfpe ähnelt: github.com/quchen/articles/blob/master/
0 Stimmen
Siehe meinen Artikel über FPComplete, in dem ich erkläre, WARUM man Monaden verwenden sollte (nicht wie sie funktionieren): bit.ly/MH9zRD
2 Stimmen
Die beste Erklärung, die ich bisher gehört habe, stammt von wikipedia: "Monaden sind programmierbare Semikolons."
0 Stimmen
Ich bin auf diesen Artikel gestoßen: stephanboyer.com/post/9/monads-part-1-a-design-pattern . Ich fand es ist die beste und effizienteste Konzeptvermittlung für Laien wie mich bisher. Der Autor hat eigentlich auch andere Artikel für Monaden.
0 Stimmen
Eine äußerst leicht verständliche Erklärung von Douglas Crockford: youtube.com/watch?v=dkZFtimgAcM
0 Stimmen
Monade ist kein Haskell-spezifisches Konzept, @HelderPereira. Ihr Retag scheint mir falsch zu sein.
1 Stimmen
@Palec Ich weiß, aber in der Frage wird Haskell erwähnt, und die am häufigsten gewählte Antwort verwendet Haskell, um sie zu erklären. Ich dachte nur, es wäre nützlich, um es für Leute, die Haskell lernen, einfacher zu machen, es zu finden, da dies ein sehr wichtiges Konzept der Sprache ist. Es steht Ihnen jedoch frei, es zu entfernen, wenn Sie denken, dass es keinen Sinn macht.
0 Stimmen
Ich möchte sagen, dass Monade ist eine Konstruktion, die Sie alle Ihre Mist in (tun tatsächlichen Job, aka Nebenwirkungen), und präsentieren Sie eine schicke Box, um Ihren Code functionnal (lesen Sie Nebeneffekt frei).
0 Stimmen
Monad ist EDSL. Siehe este : "Irgendwann bemerkte jemand: "Oh, um unreine Effekte aus reinem Code zu erhalten, muss ich Metaprogrammierung betreiben, was bedeutet, dass einer meiner Typen 'Programme, die ein X berechnen' sein muss. Ich möchte ein 'Programm, das ein X berechnet' und eine Funktion, die ein X nimmt und das nächste Programm erzeugt, ein 'Programm, das ein Y berechnet', nehmen und sie irgendwie zu einem 'Programm, das ein Y berechnet' zusammenfügen" (das ist die Bindungsoperation). Die IO-Monade war geboren."
0 Stimmen
Dieser Artikel von Tomasz Nurkiewicz ist die beste Erklärung, die ich für Java-Entwickler gefunden habe.
0 Stimmen
Kürzer: Monade ist (eingebettetes) Interpreter-Muster (wobei Anweisungen der zu interpretierenden Sprache erstklassige Werte unserer Programmiersprache selbst sind).
0 Stimmen
Monaden sind eingebettete domänenspezifische Sprachen, die Anweisungen (Semikolons) enthalten. Die Semikolons können Anweisungen in traditionellen prozeduralen Sprachen, Joins in SQL oder was immer Sie wollen darstellen. Da man Monaden zusammenführen kann, um Sprachen mit einer reicheren Semantik zu bilden, oder Monaden aufteilen kann, kann man Monaden auch als die SEMANTIK der Sprachen selbst betrachten.
2 Stimmen
Leider ist eine Monade eine Sache, die nur von Leuten erklärt werden kann, die nicht wissen, wie man etwas erklärt.