918 Stimmen

Eine Monade ist einfach ein Monoid in der Kategorie der Endofunktionen, wo ist das Problem?

Wer hat zuerst Folgendes gesagt?

Eine Monade ist einfach ein Monoid in der Kategorie der Endofunktionen, wo liegt das Problem?

Und eine weniger wichtige Anmerkung, ist dies wahr, und wenn ja, könnten Sie eine Erklärung geben (hoffentlich eine, die von jemandem verstanden werden kann, die nicht viel Haskell Erfahrung haben)?

25 Stimmen

Siehe "Kategorien für den Arbeitsmathematiker".

37 Stimmen

Sie müssen das nicht verstehen, um Monaden in Haskell zu verwenden. Aus praktischer Sicht sind sie nur ein cleverer Weg, um "Zustände" durch unterirdische Leitungen weiterzuleiten.

3 Stimmen

Ich möchte auch diesen ausgezeichneten Blogbeitrag hier hinzufügen: stephendiehl.com/posts/monads.html Es beantwortet zwar nicht direkt die Frage, aber meiner Meinung nach leistet Stephen eine hervorragende Arbeit, um Kategorien und Monaden in Haskell miteinander zu verbinden. Wenn Sie die obigen Antworten gelesen haben, sollte dies helfen, die beiden Sichtweisen zu vereinen.

964voto

Tom Crockett Punkte 29618

Diese Formulierung stammt von James Iry, aus seinem höchst unterhaltsamen Kurze, unvollständige und größtenteils falsche Geschichte der Programmiersprachen in dem er es fiktiv Philip Wadler zuschreibt.

Das Originalzitat stammt von Saunders Mac Lane in Kategorien für den Arbeitsmathematiker einer der Grundlagentexte der Kategorientheorie. Hier ist es im Kontext die wahrscheinlich der beste Ort ist, um zu erfahren, was es genau bedeutet.

Aber ich werde einen Versuch wagen. Der ursprüngliche Satz lautet wie folgt:

Alles in allem ist eine Monade in X einfach ein Monoid in der Kategorie der Endofunktoren von X, wobei das Produkt × durch die Komposition von Endofunktoren und die Einheitsmenge durch den Identitätsendofaktor ersetzt wird.

X hier ist eine Kategorie. Endofunktoren sind Funktoren von einer Kategorie zu sich selbst (das ist normalerweise alle Functor s, soweit es funktionale Programmierer betrifft, da sie meist nur mit einer Kategorie zu tun haben: der Kategorie der Typen - aber ich schweife ab). Aber man könnte sich eine weitere Kategorie vorstellen, nämlich die Kategorie der "Endofunktionen auf X ". Dies ist eine Kategorie, in der die Objekte Endofunktoren und die Morphismen natürliche Transformationen sind.

Und von diesen Endofunktoren könnten einige Monaden sein. Welche davon sind Monaden? Genau die, die es sind monoidal in einem besonderen Sinne. Anstatt die genaue Zuordnung von Monaden zu Monoiden zu erläutern (da Mac Lane das viel besser kann als ich), werde ich einfach die jeweiligen Definitionen nebeneinander stellen und Sie vergleichen lassen:

Ein Monoid ist...

  • Ein Satz, S
  • Eine Operation, - : S × S S
  • Ein Element der S , e : 1 S

...die diese Gesetze erfüllen:

  • (a - b) - c = a - (b - c) für alle a , b et c sur S
  • e - a = a - e = a für alle a sur S

Eine Monade ist...

  • Ein Endofunctor, T : X X (in Haskell: ein Typkonstruktor der Art * -> * mit einer Functor Instanz)
  • Eine natürliche Transformation, : T × T T , wobei × bedeutet Funktorkomposition ( ist bekannt als join in Haskell)
  • Eine natürliche Transformation, : I T , wobei I ist der Identitätsendofunktor auf X ( ist bekannt als return in Haskell)

...die diese Gesetze erfüllen:

  • T = T
  • T = T = 1 (die natürliche Umwandlung der Identität)

Mit ein bisschen Blinzeln können Sie vielleicht erkennen, dass beide Definitionen Instanzen desselben abstraktes Konzept .

107voto

Luis Casillas Punkte 29236

Zunächst zu den Erweiterungen und Bibliotheken, die wir verwenden werden:

{-# LANGUAGE RankNTypes, TypeOperators #-}

import Control.Monad (join)

Von diesen, RankNTypes ist die einzige, die für das Folgende absolut notwendig ist. Ich habe einmal eine Erklärung geschrieben über RankNTypes die einige Leute anscheinend als nützlich empfunden haben Ich werde mich also darauf beziehen.

Zitat Tom Crocketts ausgezeichnete Antwort haben wir:

Eine Monade ist...

  • Ein Endofunctor, T : X -> X
  • Eine natürliche Transformation, : T × T -> T , wobei × bedeutet Funktorkomposition
  • Eine natürliche Transformation, : I -> T , wobei I ist der Identitätsendofunktor auf X

...die diese Gesetze erfüllen:

  • ((T × T) × T)) = (T × (T × T))
  • ((T)) = T = (T())

Wie lässt sich dies in Haskell-Code übersetzen? Nun, beginnen wir mit dem Begriff einer natürliche Umwandlung :

-- | A natural transformations between two 'Functor' instances.  Law:
--
-- > fmap f . eta g == eta g . fmap f
--
-- Neat fact: the type system actually guarantees this law.
--
newtype f :-> g =
    Natural { eta :: forall x. f x -> g x }

Ein Typ der Form f :-> g ist analog zu einem Funktionstyp, aber anstatt ihn als Funktion zwischen zwei Typen (von Art * ), betrachten Sie es als eine Morphismus zwischen zwei Funktoren (jeweils von der Art * -> * ). Beispiele:

listToMaybe :: [] :-> Maybe
listToMaybe = Natural go
    where go [] = Nothing
          go (x:_) = Just x

maybeToList :: Maybe :-> []
maybeToList = Natural go
    where go Nothing = []
          go (Just x) = [x]

reverse' :: [] :-> []
reverse' = Natural reverse

Grundsätzlich sind in Haskell natürliche Transformationen Funktionen von einem Typ f x zu einer anderen Art g x so dass die x Typvariable für den Aufrufer "unzugänglich" ist. Also zum Beispiel, sort :: Ord a => [a] -> [a] kann nicht in eine natürliche Transformation umgewandelt werden, da es "wählerisch" ist, welche Typen wir für a . Eine intuitive Methode, die ich oft verwende, um dies zu verstehen, ist die folgende:

  • Ein Funktor ist eine Möglichkeit, mit dem Inhalt von etwas ohne Berührung des Struktur .
  • Eine natürliche Umwandlung ist eine Art und Weise, auf die Struktur von etwas, ohne es zu berühren oder zu betrachten Inhalt .

Nachdem dies nun geklärt ist, wollen wir uns nun den Klauseln der Definition widmen.

Der erste Satz lautet "ein Endofunctor", T : X -> X ." Nun, jeder Functor in Haskell ist ein Endofunctor in der so genannten "Hask-Kategorie", deren Objekte Haskell-Typen sind (vom Typ * ) und deren Morphismen Haskell-Funktionen sind. Das klingt nach einer komplizierten Aussage, ist aber eigentlich sehr trivial. Es bedeutet lediglich, dass ein Functor f :: * -> * gibt Ihnen die Möglichkeit, einen Typ zu konstruieren f a :: * für jede a :: * und eine Funktion fmap f :: f a -> f b aus einem beliebigen f :: a -> b und dass diese den Funktorengesetzen gehorchen.

Zweiter Satz: Die Identity Funktor in Haskell (der mit der Plattform mitgeliefert wird, Sie können ihn also einfach importieren) ist folgendermaßen definiert:

newtype Identity a = Identity { runIdentity :: a }

instance Functor Identity where
    fmap f (Identity a) = Identity (f a)

Die natürliche Umwandlung : I -> T aus der Definition von Tom Crockett kann auf diese Weise für jede Monad Instanz t :

return' :: Monad t => Identity :-> t
return' = Natural (return . runIdentity)

Dritter Satz: Die Komposition von zwei Funktoren in Haskell kann auf diese Weise definiert werden (was auch mit der Plattform geschieht):

newtype Compose f g a = Compose { getCompose :: f (g a) }

-- | The composition of two 'Functor's is also a 'Functor'.
instance (Functor f, Functor g) => Functor (Compose f g) where
    fmap f (Compose fga) = Compose (fmap (fmap f) fga)

Die natürliche Umwandlung : T × T -> T aus der Definition von Tom Crockett kann wie folgt geschrieben werden:

join' :: Monad t => Compose t t :-> t
join' = Natural (join . getCompose)

Die Aussage, dass dies ein Monoid in der Kategorie der Endofunktionen ist, bedeutet dann, dass Compose (teilweise nur auf seine ersten beiden Parameter angewandt) assoziativ ist und dass Identity ist sein Identitätselement. D. h., dass die folgenden Isomorphismen gelten:

  • Compose f (Compose g h) ~= Compose (Compose f g) h
  • Compose f Identity ~= f
  • Compose Identity g ~= g

Diese sind sehr leicht zu beweisen, denn Compose et Identity sind beide definiert als newtype und die Haskell-Berichte definieren die Semantik von newtype als Isomorphismus zwischen dem Typ, der definiert wird, und dem Typ des Arguments der newtype Datenkonstrukteur. Lassen Sie uns also zum Beispiel beweisen Compose f Identity ~= f :

Compose f Identity a
    ~= f (Identity a)                 -- newtype Compose f g a = Compose (f (g a))
    ~= f a                            -- newtype Identity a = Identity a
Q.E.D.

29voto

Dmitri Zaitsev Punkte 12685

Die hier gegebenen Antworten leisten hervorragende Arbeit bei der Definition von Monoiden und Monaden, aber sie scheinen die Frage nicht zu beantworten:

Und eine weniger wichtige Anmerkung, ist dies wahr, und wenn ja, könnten Sie eine Erklärung geben (hoffentlich eine, die von jemandem verstanden werden kann, die nicht viel Haskell Erfahrung haben)?

Der springende Punkt, der hier fehlt, ist der andere Begriff des "Monoids", das sogenannte Kategorisierung genauer gesagt: die eines Monoids in einer monoidalen Kategorie. Leider ist das Buch von Mac Lane selbst macht es sehr verwirrend :

Alles in allem ist eine Monade in X ist nur ein Monoid in der Kategorie der Endofunktionen von X mit Produkt × durch die Komposition von Endofunktoren und die Einheitsmenge durch den Identitätsendofaktor ersetzt.

Hauptverwirrung

Warum ist das verwirrend? Weil es nicht definiert, was ein "Monoid in der Kategorie der Endofunktionen" von X . Stattdessen schlägt dieser Satz vor, ein Monoid innerhalb von die Menge aller Endofunktoren zusammen mit dem Funktor Komposition als binäre Operation und dem Identitätsfunktor als monoidale Einheit. Das funktioniert perfekt und macht aus jeder Teilmenge von Endofunktoren, die den Identitätsfunktor enthält und unter Funktorkomposition geschlossen ist, ein Monoid.

Dies ist jedoch nicht die richtige Interpretation, was das Buch an dieser Stelle nicht deutlich macht. Eine Monade f es un fest Endofunctor, nicht eine Teilmenge von Endofunctoren, die unter Komposition geschlossen ist. Eine übliche Konstruktion ist die Verwendung von f a erzeugen ein Monoid, indem man die Menge aller k -Fachkompositionen f^k = f(f(...)) von f mit sich selbst, einschließlich k=0 die der Identität entspricht f^0 = id . Und jetzt das Set S von all diesen Kräften für alle k>=0 ist in der Tat ein Monoid, "bei dem das Produkt × durch die Komposition von Endofunktoren und die Einheitsmenge durch den Identitätsendofaktor ersetzt wird".

Und doch:

  • Dieses Monoid S kann für jeden Funktor definiert werden f oder sogar buchstäblich für jede Selbstdarstellung von X . Es ist das Monoid erzeugt durch f .
  • Die monoidale Struktur von S die durch den Funktor Komposition und den Identitätsfunktor gegeben ist, hat nichts zu tun mit f eine Monade zu sein oder nicht zu sein.

Und um die Dinge noch verwirrender zu machen, kommt die Definition von "Monoid in monoidaler Kategorie" erst später im Buch, wie man aus der inhaltsverzeichnis . Und doch ist das Verständnis dieses Begriffs absolut entscheidend für das Verständnis der Verbindung mit Monaden.

(Streng) monoidale Kategorien

In Kapitel VII über Monoide (das später folgt als Kapitel VI über Monaden) finden wir die Definition des sogenannten strenge Monoidalkategorie als Dreifach (B, *, e) , wobei B ist eine Kategorie, *: B x B-> B a Bifunktor (Funktor in Bezug auf jede Komponente mit fester anderer Komponente) und e ist ein Einheitsobjekt in B , die die Assoziativitäts- und Einheitsgesetze erfüllen:

(a * b) * c = a * (b * c)
a * e = e * a = a

für beliebige Objekte a,b,c von B und die gleichen Identitäten für alle Morphismen a,b,c con e ersetzt durch id_e , der Identitätsmorphismus von e . Es ist nun lehrreich zu beobachten, dass in unserem Fall, der uns interessiert, wo B ist die Kategorie der Endofunktoren von X mit natürlichen Transformationen als Morphismen, * die Funktorkomposition und e des Identitätsfaktors sind alle diese Gesetze erfüllt, wie direkt überprüft werden kann.

Was in dem Buch folgt, ist die Definition des "entspannten" monoidale Kategorie wobei die Gesetze nur modulo einiger fester natürlicher Transformationen gelten, die die so genannten Kohärenzbeziehungen was jedoch für unsere Fälle der Endofunktorkategorien nicht wichtig ist.

Monoide in monoidalen Kategorien

In Kapitel VII, Abschnitt 3 "Monoide", wird schließlich die eigentliche Definition gegeben:

Ein Monoid c in einer monoidalen Kategorie (B, *, e) ist ein Objekt von B mit zwei Pfeilen (Morphismen)

mu: c * c -> c
nu: e -> c

wodurch 3 Diagramme kommutativ werden. Es sei daran erinnert, dass es sich in unserem Fall um Morphismen in der Kategorie der Endofunktoren handelt, die natürliche Transformationen sind, die genau join et return für eine Monade. Der Zusammenhang wird noch deutlicher, wenn wir die Komposition * expliziter, indem er die c * c von c^2 , wobei c ist unsere Monade.

Schließlich ist zu beachten, dass die drei kommutativen Diagramme (in der Definition eines Monoids in einer monoidalen Kategorie) für allgemeine (nicht-strikte) monoidale Kategorien geschrieben sind, während in unserem Fall alle natürlichen Transformationen, die als Teil der monoidalen Kategorie auftreten, tatsächlich Identitäten sind. Damit sind die Diagramme genau die gleichen wie die in der Definition einer Monade, so dass die Korrespondenz vollständig ist.

結論

Zusammenfassend lässt sich sagen, dass jede Monade per Definition ein Endofunktor ist, also ein Objekt in der Kategorie der Endofunktoren, wobei die monadische join et return Operatoren erfüllen die Definition von ein Monoid in dieser bestimmten (strengen) monoidalen Kategorie . Umgekehrt ist jedes Monoid in der monoidalen Kategorie der Endofunktionen per Definition ein Tripel (c, mu, nu) bestehend aus einem Objekt und zwei Pfeilen, in unserem Fall z.B. natürlichen Transformationen, die denselben Gesetzen wie eine Monade genügen.

Beachten Sie schließlich den entscheidenden Unterschied zwischen den (klassischen) Monoiden und den allgemeineren Monoiden in monoidalen Kategorien. Die beiden Pfeile mu et nu oben sind nicht mehr eine binäre Operation und eine Einheit in einer Menge. Stattdessen hat man einen festen Endofunctor c . Die Funktorkomposition * und der Identitätsfunktor allein bieten nicht die vollständige Struktur, die für die Monade benötigt wird, trotz dieser verwirrenden Bemerkung im Buch.

Ein anderer Ansatz wäre der Vergleich mit dem Standardmonoid C aller Selbstabbildungen einer Menge A wobei die binäre Operation die Komposition ist, die als Abbildung des kartesischen Standardprodukts C x C in C . Wenn wir zum kategorisierten Monoid übergehen, ersetzen wir das kartesische Produkt x mit der Funktorkomposition * , und die binäre Operation wird durch die natürliche Transformation ersetzt mu von c * c a c das ist eine Sammlung der join Betreiber

join: c(c(T))->c(T)

für jedes Objekt T (Programmierung eintippen). Und die Identitätselemente in klassischen Monoiden, die mit Bildern von Karten aus einer festen Ein-Punkt-Menge identifiziert werden können, werden durch die Sammlung der return Betreiber

return: T->c(T) 

Nun gibt es aber keine kartesischen Produkte mehr, also keine Paare von Elementen und damit keine binären Operationen.

9voto

Edmund's Echo Punkte 574

Ich bin zu diesem Beitrag gekommen, weil ich die Schlussfolgerung des berüchtigten Zitats aus Mac Lane's Kategorientheorie für den arbeitenden Mathematiker .

Wenn man beschreibt, was etwas ist, ist es oft ebenso nützlich zu beschreiben, was es nicht ist.

Die Tatsache, dass Mac Lane die Beschreibung verwendet, um eine Monade zu beschreiben, könnte darauf hindeuten, dass sie etwas beschreibt, das nur für Monaden gilt. Seien Sie nachsichtig mit mir. Um ein breiteres Verständnis der Aussage zu entwickeln, muss meines Erachtens deutlich gemacht werden, dass er no beschreibt etwas, das es nur bei Monaden gibt; die Aussage gilt auch für Applicative und Arrows und andere. Aus demselben Grund, aus dem wir zwei Monoide auf Int (Summe und Produkt) haben können, können wir mehrere Monoide auf X in der Kategorie der Endofunktionen haben. Aber die Ähnlichkeiten gehen noch weiter.

Sowohl Monad als auch Applicative erfüllen die Kriterien:

  • endo => jeder Pfeil oder Morphismus, der an der gleichen Stelle beginnt und endet

  • Funktor => beliebiger Pfeil oder Morphismus zwischen zwei Kategorien

    (z. B. im täglichen Leben Tree a -> List b sondern in der Kategorie Tree -> List )

  • monoid => einzelnes Objekt; d.h. ein einziger Typ, aber in diesem Zusammenhang nur in Bezug auf die externe Schicht; wir können also nicht Tree -> List nur List -> List .

Die Erklärung verwendet "Kategorie von...". Damit wird der Geltungsbereich der Aussage definiert. Als Beispiel beschreibt die Functor Category den Geltungsbereich von f * -> g * d.h., Any functor -> Any functor , z.B., Tree * -> List * o Tree * -> Tree * .

Was eine kategorische Aussage nicht angibt, beschreibt, wo alles und jedes ist erlaubt .

In diesem Fall innerhalb der Funktoren, * -> * alias a -> b nicht angegeben ist, was bedeutet Anything -> Anything including Anything else . Da meine Vorstellungskraft auf Int -> String überspringt, beinhaltet sie auch Integer -> Maybe Int oder sogar Maybe Double -> Either String Int donde a :: Maybe Double; b :: Either String Int .

Die Erklärung lässt sich also wie folgt zusammenfassen:

  • Funktorbereich :: f a -> g b (d.h. jeder parametrisierte Typ zu jedem parametrisierten Typ)
  • endo + functor :: f a -> f b (d.h. ein beliebiger parametrisierter Typ auf denselben parametrisierten Typ) ... anders gesagt,
  • ein Monoid in der Kategorie der Endofunktoren

Wo liegt also die Kraft dieses Konstrukts? Um die volle Dynamik zu verstehen, musste ich sehen, dass die typischen Zeichnungen eines Monoids (ein einzelnes Objekt mit einem Pfeil, der wie eine Identität aussieht) nicht ausreichen, :: single object -> single object ), zeigt nicht, dass ich einen Pfeil verwenden darf, der mit beliebige Nummer von monoiden Werten, aus dem eine Typ Objekt in Monoid erlaubt. Die endo, ~ Identitätspfeil-Definition der Äquivalenz ignoriert des Funktors Typwert und sowohl den Typ als auch den Wert der innersten Schicht, der "Nutzlast". Somit ergibt die Äquivalenz true in jeder Situation, in der die Funktionstypen übereinstimmen (z. B., Nothing -> Just * -> Nothing ist gleichbedeutend mit Just * -> Just * -> Just * denn sie sind beide Maybe -> Maybe -> Maybe ).

Sidebar: ~ outside ist begrifflich, aber es ist das Symbol ganz links in f a . Es beschreibt auch, was "Haskell" zuerst einliest (großes Bild); so ist Type "draußen" in Bezug auf einen Type Value. Die Beziehung zwischen Ebenen (eine Kette von Referenzen) in der Programmierung ist in der Kategorie nicht einfach zu beschreiben. Die Kategorie der Menge wird verwendet, um Typen (Int, Strings, Maybe Int usw.) zu beschreiben, die die Kategorie des Funktors (parametrisierte Typen) einschließt. Die Referenzkette: Funktortyp, Funktorwerte (Elemente der Menge dieses Funktors, z. B. Nothing, Just) und wiederum alles andere, worauf jeder Funktorwert verweist. In Category wird die Beziehung anders beschrieben, z.B., return :: a -> m a wird als eine natürliche Transformation von einem Funktor in einen anderen Funktor betrachtet, die sich von allen bisher genannten unterscheidet.

Zurück zum Hauptthema: Alles in allem beschreibt die Aussage für jedes definierte Tensorprodukt und einen neutralen Wert ein erstaunlich leistungsfähiges Berechnungskonstrukt, das aus seiner paradoxen Struktur entsteht:

  • nach außen hin erscheint es als ein einziges Objekt (z.B., :: List ); statisch
  • aber im Inneren eine Menge Dynamik zulässt
    • eine beliebige Anzahl von Werten desselben Typs (z. B. Empty | ~NonEmpty) als Futter für Funktionen beliebiger Arität. Das Tensorprodukt reduziert eine beliebige Anzahl von Eingaben auf einen einzigen Wert... für die externe Schicht (~ fold die nichts über die Nutzlast aussagt)
    • unendliche Reihe von beide den Typ und die Werte für die innerste Schicht

In Haskell ist die Klärung der Anwendbarkeit der Anweisung wichtig. Die Macht und Vielseitigkeit dieses Konstrukts hat absolut nichts mit einer Monade an sich zu tun. Mit anderen Worten, das Konstrukt beruht nicht auf dem, was eine Monade einzigartig macht.

Wenn man versucht, herauszufinden, ob man Code mit einem gemeinsamen Kontext erstellen soll, um Berechnungen zu unterstützen, die voneinander abhängen, oder Berechnungen, die parallel ausgeführt werden können, ist diese berüchtigte Aussage, so viel sie auch beschreibt, kein Gegensatz zwischen der Wahl von Applicative, Arrows und Monads, sondern eher eine Beschreibung, wie sehr sie gleich sind. Für die vorliegende Entscheidung ist die Aussage überflüssig.

Dies wird oft missverstanden. In der Erklärung wird weiter beschrieben join :: m (m a) -> m a als Tensorprodukt für den monoidalen Endofunktor. Es wird jedoch nicht dargelegt, wie im Zusammenhang mit dieser Aussage, (<*>) hätte auch gewählt werden können. Es ist wirklich ein Beispiel für 'sechs in einem, ein halbes Dutzend im anderen'. Die Logik für die Kombination von Werten ist genau gleich; dieselbe Eingabe erzeugt dieselbe Ausgabe (im Gegensatz zu den Summen- und Produktmonoiden für Int, da sie bei der Kombination von Ints unterschiedliche Ergebnisse erzeugen).

Also, um es noch einmal zusammenzufassen: Ein Monoid in der Kategorie der Endofunktoren beschreibt:

 ~t :: m * -> m * -> m *
 and a neutral value for m *

(<*>) et (>>=) beide ermöglichen den gleichzeitigen Zugang zu den beiden m Werte, um den einzelnen Rückgabewert zu berechnen. Die Logik, mit der der Rückgabewert berechnet wird, ist genau dieselbe. Wären da nicht die unterschiedlichen Formen der Funktionen, die sie parametrisieren ( f :: a -> b gegen k :: a -> m b ) und die Position des Parameters mit demselben Rückgabetyp der Berechnung (d. h., a -> b -> b gegen b -> a -> b für beide), so vermute ich, dass wir die monoidale Logik, das Tensorprodukt, zur Wiederverwendung in beiden Definitionen hätten parametrisieren können. Versuchen Sie zur Veranschaulichung, Folgendes zu implementieren ~t und am Ende erhält man (<*>) et (>>=) je nachdem, wie Sie es definieren möchten forall a b .

Wenn mein letzter Punkt zumindest konzeptionell zutreffend ist, dann erklärt er den genauen und einzigen rechnerischen Unterschied zwischen Applicative und Monad: die Funktionen, die sie parametrisieren. Mit anderen Worten, der Unterschied ist extern zur Implementierung dieser Typklassen.

Abschließend kann ich sagen, dass Mac Lanes berüchtigtes Zitat für mich ein großartiges "goto"-Memo war, ein Wegweiser, auf den ich mich beziehen konnte, während ich mich durch die Kategorie navigierte, um die in Haskell verwendeten Idiome besser zu verstehen. Es gelingt, den Umfang einer mächtigen Rechenkapazität zu erfassen, die in Haskell auf wunderbare Weise zugänglich gemacht wird.

Es liegt jedoch eine gewisse Ironie darin, dass ich die Anwendbarkeit der Aussage außerhalb der Monade zunächst missverstanden habe, was ich hier hoffentlich vermittelt habe. Alles, was sie beschreibt, stellt sich als das heraus, was zwischen Applicative und Monads (und Arrows unter anderem) ähnlich ist. Was sie nicht sagt, ist genau der kleine, aber nützliche Unterschied zwischen ihnen.

7voto

hobbs Punkte 204816

Note : Nein, das ist nicht wahr. Irgendwann gab es einen Kommentar zu dieser Antwort von Dan Piponi selbst, in dem er sagte, dass Ursache und Wirkung hier genau das Gegenteil waren, dass er seinen Artikel als Antwort auf James Irys Scherz geschrieben hat. Aber er scheint entfernt worden zu sein, vielleicht von einem zwanghaften Aufräumer.

Nachstehend finden Sie meine ursprüngliche Antwort.


Es ist durchaus möglich, dass Iry gelesen hatte Von Monoiden zu Monaden ein Beitrag, in dem Dan Piponi (sigfpe) Monaden aus Monoiden in Haskell ableitet, mit viel Diskussion der Kategorientheorie und ausdrücklicher Erwähnung der "Kategorie der Endofunktionen auf Hask " . Wer sich fragt, was es bedeutet, dass eine Monade ein Monoid in der Kategorie der Endofunktionen ist, könnte von der Lektüre dieser Ableitung jedenfalls profitieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X