Eine Sache, die es verwirrend macht, ist, dass die "populären" Funktionen wie bind
und <*>
praxisorientiert sind. Um die Konzepte zu verstehen, ist es jedoch einfacher, zuerst andere Funktionen zu betrachten. Es ist auch erwähnenswert, dass Monaden hervorstechen, weil sie im Vergleich zu anderen verbundenen Konzepten etwas überzeichnet sind. Also werde ich stattdessen mit Funktoren beginnen.
Funktoren bieten eine Funktion (in Haskell-Notation) fmap :: (Functor f) => (a -> b) -> f a -> f b
. Mit anderen Worten, Sie haben einen Kontext f
, in den Sie eine Funktion heben können. Wie Sie sich vorstellen können, ist fast alles ein Funktor. Listen, Vielleicht, Entweder, Funktionen, I / O, Tupel, Parser ... Jedes repräsentiert einen Kontext, in dem ein Wert erscheinen kann. So können Sie äußerst vielseitige Funktionen schreiben, die in nahezu jedem Kontext mit fmap
oder in der Inline-Variante funktionieren<$>
.
Was möchten Sie sonst noch mit Kontexten machen? Möglicherweise möchten Sie zwei Kontexte kombinieren. Vielleicht möchten Sie eine Verallgemeinerung vonzip :: [a] -> [b] -> [(a,b)]
zum Beispiel wie folgt aus : pair :: (Monoidal f) => f a -> f b -> f (a,b)
.
Aber weil es in der Praxis noch nützlicher ist, bieten die Haskell-Bibliotheken stattdessen Applicative
eine Kombination aus Functor
und Monoidal
und Unit
, die nur hinzufügt, dass Sie tatsächlich Werte "in" Ihren Kontext einfügen könnenunit
.
Sie können äußerst allgemeine Funktionen schreiben, indem Sie nur diese drei Dinge über den Kontext angeben, in dem Sie arbeiten.
Monad
ist nur eine andere Sache, die Sie dazu sagen können. Was ich vorher nicht erwähnt habe, ist, dass Sie bereits zwei Möglichkeiten haben, zwei Kontexte zu kombinieren: Sie können nicht nur pair
sie, sondern Sie können sie auch stapeln, z. B. Sie können eine Liste von Listen haben. Im E / A-Kontext wäre ein Beispiel eine E / A-Aktion, die andere E / A-Aktionen aus einer Datei lesen kann, sodass Sie einen Typ hätten FilePath -> IO (IO a)
. Wie können wir dieses Stapeln loswerden, um eine ausführbare Funktion zu erhalten IO a
? Hier kommt Monad
s ins join
Spiel, es ermöglicht uns, zwei gestapelte Kontexte desselben Typs zu kombinieren. Das gleiche gilt für Parser, Vielleicht usw. Undbind
ist nur eine praktischere Art der Verwendungjoin
Ein monadischer Kontext muss also nur vier Dinge bieten und kann mit fast allen Maschinen verwendet werden, die für E / A, für Parser, für Ausfälle usw. entwickelt wurden.