Um schnelle Leser zu respektieren, beginne ich mit einer präzisen Definition, fahre dann mit einer kurzen Erklärung auf "einfachem Englisch" fort und gehe dann zu den Beispielen über.
Hier ist eine kurze und präzise Definition leicht umformuliert:
A Monade (in der Informatik) ist formell eine Karte, die:
-
sendet jede Art X
einer bestimmten Programmiersprache auf einen neuen Typ T(X)
(genannt die "Art der T
-Rechnungen mit Werten in X
");
-
mit einer Regel zum Zusammensetzen zweier Funktionen der Form f:X->T(Y)
y g:Y->T(Z)
zu einer Funktion gf:X->T(Z)
;
-
auf eine Weise, die im offensichtlichen Sinne assoziativ und in Bezug auf eine gegebene Einheitsfunktion namens pure_X:X->T(X)
ist als Übergabe eines Wertes an die reine Berechnung zu verstehen, die diesen Wert einfach zurückgibt.
Mit einfachen Worten: ein Monade es un Regel von jedem Typ zu übergeben X
zu einer anderen Art T(X)
und eine Regel zur Übergabe von zwei Funktionen f:X->T(Y)
y g:Y->T(Z)
(die Sie gerne komponieren würden, aber nicht können) in eine neue Funktion h:X->T(Z)
. Die jedoch, ist nicht die Zusammensetzung im streng mathematischen Sinne. Wir "verbiegen" im Grunde die Zusammensetzung von Funktionen oder definieren neu, wie Funktionen zusammengesetzt sind.
Außerdem muss die Kompositionsregel der Monade die "offensichtlichen" mathematischen Axiome erfüllen:
- Assoziativität : Komponieren
f
con g
und dann mit h
(von außen) sollte dasselbe sein wie das Zusammenstellen von g
con h
und dann mit f
(von innen).
- Unbewegliches Vermögen : Komponieren
f
mit dem Identität Funktion auf beiden Seiten sollte ergeben f
.
Um es noch einmal einfach auszudrücken: Wir können unsere Funktionszusammensetzung nicht nach Belieben umdefinieren:
- Wir brauchen zunächst die Assoziativität, um mehrere Funktionen in einer Reihe zusammenstellen zu können, z. B.
f(g(h(k(x)))
und sich nicht um die Angabe der Reihenfolge zu kümmern, in der die Funktionspaare gebildet werden. Da die Monadenregel nur vorschreibt, wie man eine Funktionspaar Ohne dieses Axiom müssten wir wissen, welches Paar zuerst zusammengesetzt wird, und so weiter. (Man beachte, dass dies etwas anderes ist als die Eigenschaft der Kommutativität, die f
komponiert mit g
waren die gleichen wie g
komponiert mit f
was nicht erforderlich ist).
- Und zweitens brauchen wir die Unital-Eigenschaft, die einfach besagt, dass sich Identitäten trivialerweise so zusammensetzen, wie wir es erwarten. So können wir Funktionen sicher refaktorisieren, wenn diese Identitäten extrahiert werden können.
Also noch einmal in aller Kürze: Eine Monade ist die Regel der Typerweiterung und der Kompositionsfunktionen, die die beiden Axiome - Assoziativität und Unitalität - erfüllen.
In der Praxis möchten Sie, dass die Monade für Sie von der Sprache, dem Compiler oder dem Framework implementiert wird, die sich um die Komposition von Funktionen für Sie kümmern würden. So können Sie sich auf das Schreiben der Logik Ihrer Funktionen konzentrieren und müssen sich nicht darum kümmern, wie deren Ausführung implementiert wird.
Das ist im Wesentlichen alles, kurz und bündig.
Als professioneller Mathematiker ziehe ich es vor, die Bezeichnung h
die "Zusammensetzung" von f
y g
. Denn mathematisch gesehen ist sie es nicht. Die Bezeichnung "Zusammensetzung" setzt fälschlicherweise voraus, dass h
die wahre mathematische Zusammensetzung ist, was sie nicht ist. Sie ist nicht einmal eindeutig bestimmt durch f
y g
. Stattdessen ist es das Ergebnis der neuen "Kompositionsregel" unserer Monade für die Funktionen. Diese kann sich völlig von der tatsächlichen mathematischen Zusammensetzung unterscheiden, selbst wenn diese existiert!
Um es weniger trocken zu machen, möchte ich versuchen, es an einem Beispiel zu verdeutlichen die ich mit kleinen Abschnitten kommentiere, so dass Sie gleich zur Sache kommen können.
Beispiele für das Auslösen von Ausnahmen als Monade
Angenommen, wir wollen zwei Funktionen zusammenstellen:
f: x -> 1 / x
g: y -> 2 * y
Aber f(0)
ist nicht definiert, so dass eine Ausnahme e
geworfen wird. Wie können Sie dann den Kompositionswert definieren g(f(0))
? Natürlich wieder eine Ausnahme auslösen! Vielleicht die gleiche e
. Vielleicht eine neue aktualisierte Ausnahme e1
.
Was passiert hier genau? Zunächst benötigen wir neue Ausnahmewerte (unterschiedlich oder gleich). Sie können sie aufrufen nothing
o null
oder was auch immer, aber das Wesentliche bleibt dasselbe - es sollten neue Werte sein, z.B. sollte es nicht ein number
in unserem Beispiel hier. Ich ziehe es vor, sie nicht als null
um Verwirrung zu vermeiden, wie null
kann in jeder spezifischen Sprache implementiert werden. Ebenso ziehe ich es vor, zu vermeiden nothing
weil sie häufig mit null
was im Prinzip das ist, was null
tun sollte, wird dieser Grundsatz jedoch oft aus irgendwelchen praktischen Gründen aufgeweicht.
Was genau ist eine Ausnahme?
Dies ist eine triviale Angelegenheit für jeden erfahrenen Programmierer, aber ich möchte ein paar Worte verlieren, um jeden Wurm der Verwirrung auszulöschen:
Exception ist ein Objekt, das Informationen darüber kapselt, wie das ungültige Ausführungsergebnis zustande kam.
Dies kann vom Wegwerfen aller Details bis zur Rückgabe eines einzigen globalen Wertes reichen (wie NaN
o null
) oder eine lange Protokollliste zu erstellen oder was genau passiert ist, diese an eine Datenbank zu senden und über die gesamte verteilte Datenspeicherungsschicht zu replizieren ;)
Der wichtige Unterschied zwischen diesen beiden extremen Beispielen für Ausnahmen besteht darin, dass es im ersten Fall keine Nebeneffekte . In der zweiten gibt es. Das bringt uns zu der (Tausend-Dollar-)Frage:
Sind Ausnahmen in reinen Funktionen erlaubt?
Kürzere Antwort : Ja, aber nur, wenn sie nicht zu Nebenwirkungen führen.
Längere Antwort. Um rein zu sein, muss die Ausgabe Ihrer Funktion eindeutig durch ihre Eingabe bestimmt sein. Wir ändern also unsere Funktion f
durch Senden 0
auf den neuen abstrakten Wert e
die wir als Ausnahme bezeichnen. Wir stellen sicher, dass der Wert e
keine externen Informationen enthält, die nicht eindeutig durch unsere Eingabe bestimmt sind, d. h. x
. Hier ist also ein Beispiel für eine Ausnahme ohne Nebenwirkung:
e = {
type: error,
message: 'I got error trying to divide 1 by 0'
}
Und hier ist eine mit Nebenwirkung:
e = {
type: error,
message: 'Our committee to decide what is 1/0 is currently away'
}
Eigentlich hat sie nur dann Nebenwirkungen, wenn sich diese Nachricht in Zukunft möglicherweise ändern kann. Wenn aber garantiert ist, dass sie sich nie ändert, wird dieser Wert eindeutig vorhersehbar und hat somit keine Nebenwirkung.
Um es noch dümmer zu machen. Eine Funktion, die 42
ist eindeutig rein. Aber wenn jemand Verrücktes beschließt, die 42
eine Variable, deren Wert sich ändern könnte, so ist dieselbe Funktion unter den neuen Bedingungen nicht mehr rein.
Beachten Sie, dass ich der Einfachheit halber die Objektliteralschreibweise verwende, um das Wesentliche zu verdeutlichen. Leider sind die Dinge in Sprachen wie JavaScript, wo error
ist kein Typ, der sich in Bezug auf die Funktionskomposition so verhält, wie wir es hier wollen, während tatsächliche Typen wie null
o NaN
verhalten sich nicht auf diese Weise, sondern durchlaufen einige künstliche und nicht immer intuitive Typumwandlungen.
Typ Erweiterung
Da wir die Nachricht innerhalb unserer Ausnahme variieren wollen, deklarieren wir eigentlich einen neuen Typ E
für das gesamte Ausnahmeobjekt und dann Das ist es, was die maybe number
tut, abgesehen von seinem verwirrenden Namen, der entweder vom Typ number
oder des neuen Ausnahmetyps E
also ist es wirklich die Gewerkschaft number | E
de number
y E
. Insbesondere hängt es davon ab, wie wir Folgendes konstruieren wollen E
die im Namen weder angedeutet noch reflektiert wird maybe number
.
Was ist eine funktionelle Zusammensetzung?
Es ist die mathematische Operation, die Funktionen f: X -> Y
y g: Y -> Z
und konstruieren ihre Zusammensetzung als Funktion h: X -> Z
zufriedenstellend h(x) = g(f(x))
. Das Problem mit dieser Definition tritt auf, wenn das Ergebnis f(x)
ist nicht erlaubt als Argument von g
.
In der Mathematik können diese Funktionen nicht ohne zusätzliche Arbeit zusammengesetzt werden. Die streng mathematische Lösung für unser obiges Beispiel von f
y g
ist zu entfernen 0
aus der Menge der Definitionen von f
. Mit diesem neuen Satz von Definitionen (neue restriktivere Art von x
), f
wird zusammensetzbar mit g
.
In der Programmierung ist es jedoch nicht sehr praktisch, die Definitionsmenge von f
wie diese. Stattdessen können Ausnahmen verwendet werden.
Oder es werden künstliche Werte geschaffen, wie NaN
, undefined
, null
, Infinity
usw. Sie bewerten also 1/0
à Infinity
y 1/-0
à -Infinity
. Und erzwingen Sie dann den neuen Wert zurück in Ihren Ausdruck, anstatt eine Ausnahme zu machen. Das kann zu Ergebnissen führen, die Sie vorhersehbar finden oder auch nicht:
1/0 // => Infinity
parseInt(Infinity) // => NaN
NaN < 0 // => false
false + 1 // => 1
Und schon sind wir wieder bei den normalen Zahlen und können weitermachen ;)
JavaScript erlaubt es uns, numerische Ausdrücke um jeden Preis auszuführen, ohne Fehler wie im obigen Beispiel zu machen. Das heißt, es erlaubt auch, Funktionen zu komponieren. Und genau darum geht es bei der Monade - sie ist eine Regel für die Zusammenstellung von Funktionen, die die zu Beginn dieser Antwort definierten Axiome erfüllen.
Aber ist die Regel der Kompositionsfunktion, die sich aus der JavaScript-Implementierung für den Umgang mit numerischen Fehlern ergibt, eine Monade?
Zur Beantwortung dieser Frage genügt es, die Axiome zu überprüfen (als Übung belassen, da sie hier nicht Teil der Frage sind).
Kann das Auslösen einer Ausnahme zur Konstruktion einer Monade verwendet werden?
Eine nützlichere Monade wäre stattdessen die Regel, die vorschreibt dass, wenn f
wirft eine Ausnahme für einige x
so auch seine Zusammensetzung mit einem beliebigen g
. Und machen Sie die Ausnahme E
global eindeutig mit nur einem möglichen Wert ( Terminalobjekt in der Kategorientheorie). Jetzt sind die beiden Axiome sofort überprüfbar und wir erhalten eine sehr nützliche Monade. Und das Ergebnis ist das, was bekannt ist als die vielleicht Monade .
10 Stimmen
Dieser Blogbeitrag ist sehr gut: blog.sigfpe.com/2006/08/du-könntest-die-Monaden-erfunden-haben.html
6 Stimmen
Mögliche Nachbildungen: stackoverflow.com/questions/129534/what-are-monads stackoverflow.com/questions/2366/can-anyone-explain-monads
0 Stimmen
Da praktisch jeder, der sich mit Monaden befasst, bereits ein paar OOP-Sprachen kennt, wird die Frage "Erklären Sie Monaden" in der Regel für OOP-Programmierer beantwortet. Außerdem bezieht sich der von Pascal empfohlene Blogbeitrag auf C++ als Beispielsprache. Daher habe ich dafür gestimmt, den Beitrag als Duplikat zu schließen (von stackoverflow.com/questions/2366/can-anyone-explain-monads ), und ich rate allen, dasselbe zu tun.
11 Stimmen
@Pavel: Die Antwort, die wir unten von Eric erhalten haben, lautet viel besser als die in den anderen vorgeschlagenen Fragen für Leute mit einem OO-Hintergrund (im Gegensatz zu einem FP-Hintergrund).
0 Stimmen
Meta-Thread zu dieser Frage: meta.stackexchange.com/questions/47746/
5 Stimmen
@Donal: Wenn diese es ein Duplikat (zu dem ich keine Meinung habe), sollte die gute Antwort dem Original hinzugefügt werden. Das heißt: Eine gute Antwort schließt nicht aus, dass sie als Duplikat geschlossen wird. Wenn es sich um ein Duplikat handelt, das eng genug ist, kann dies von einem Moderator als Zusammenführung durchgeführt werden.
3 Stimmen
Siehe auch: stackoverflow.com/questions/674855/
0 Stimmen
Eine Monade ist eine Reihe von Funktionen mit Hilfsoperationen. Siehe diese Antwort unten
0 Stimmen
@the_drow Der erste Link scheint tot zu sein.
0 Stimmen
@DmitriZaitsev es ist nicht tot, es ist gelöscht, und ist sichtbar für Benutzer mit über 10k rep IIRC. aber es ist weitgehend irrelevant, sagt nicht viel, kann sicher ignoriert werden. gibt wenige Links, wie strongtyped.blogspot.com/2010/01/monad-non-tutorial.html ...
0 Stimmen
@the_drow Danke für die Klarstellung, aber wenn es irrelevant und für die meisten Nutzer nicht einmal sichtbar ist, warum wird es dann so erwähnt, ohne es klar zu sagen? Zumal der Begriff "dups" auf dieser Plattform häufig in einer negativen Konnotation verwendet wird, um zu implizieren, dass "die Leute ihre Hausaufgaben besser gemacht haben sollten".
0 Stimmen
@the_drow Der Blog-Link ist in der Tat lustig und der Grund, warum ich das schreiben musste: medium.com/@dmitri145/
0 Stimmen
@DmitriZaitsev Ich bin nicht die_drow. Ich habe gerade Ihren Kommentar gesehen und wollte helfen. Dieser Beitrag wurde "gelöscht 6 Aug '13 um 20:13". the_drow's Kommentar wurde "Apr 24 '10 um 13:54" gemacht.