Dies ist wahrscheinlich nicht die Antwort, die Sie suchen, aber hier geht es sowieso:
Ein wirklich krumme Weg bei Monaden suchen & co.
Eine Möglichkeit, abstrakte Konzepte wie diese zu betrachten, besteht darin, sie mit grundlegenden Konzepten wie gewöhnlichen Listenverarbeitungsoperationen zu verknüpfen. Dann könnten Sie das sagen,
- Eine Kategorie verallgemeinert die
(.)
Operation.
- Ein Monoid verallgemeinert die
(++)
Operation.
- Ein Funktor verallgemeinert die
map
Operation.
- Ein anwendbarer Funktor verallgemeinert die
zip
(oder zipWith
) Operation.
- Eine Monade verallgemeinert die
concat
Operation.
A Kategorie
Eine Kategorie von einem Satz (oder einer Klasse) von Objekten und Bündel von Pfeilen besteht, die jeweils zwei der Objekte verbinden. Außerdem sollte für jedes Objekt ein Identitätspfeil vorhanden sein, der dieses Objekt mit sich selbst verbindet. Wenn es einen Pfeil (f
) gibt, der auf einem Objekt endet, und einen anderen (g
), der von demselben Objekt aus beginnt, sollte es außerdem einen zusammengesetzten Pfeil mit der Bezeichnung g . f
geben.
In Haskell wird dies als eine Typklasse modelliert, die die Kategorie der Haskell-Typen als Objekte darstellt.
class Category cat where
id :: cat a a
(.) :: cat b c -> cat a b -> cat a c
Grundlegende Beispiele für eine Kategorie sind Funktionen. Jede Funktion verbindet zwei Typen, für alle Typen gibt es die Funktion id :: a -> a
, die den Typ (und den Wert) mit sich selbst verbindet. Die Zusammensetzung der Funktionen ist die gewöhnliche Funktionszusammensetzung.
Kurz gesagt, Kategorien in Haskell Basis sind Dinge, die verhalten sich wie Funktionen, d. H. Sie können nacheinander mit einer verallgemeinerten Version von (.)
setzen.
A Monoid
monoid A ist eine Gruppe mit einem Einheitselement und einem assoziativen Betrieb. Dies ist ein Modell in Haskell als:
class Monoid a where
mempty :: a
mappend :: a -> a -> a
Gängige Beispiele für Monoide umfassen:
- Menge der ganzen Zahlen, das Element 0, und die Operation
(+)
.
- Satz positiver Ganzzahlen, das Element 1 und die Operation
(*)
.
- Set aller Listen, die leere Liste
[]
und die Operation (++)
. Diese
modelliert in Haskell als
newtype Sum a = Sum {getSum :: a}
instance (Num a) => Monoid (Sum a) where
mempty = Sum 0
mappend (Sum a) (Sum b) = Sum (a + b)
instance Monoid [a] where
mempty = []
mappend = (++)
Monoide verwendet werden, um 'verbinden' und akkumulieren Dinge. Zum Beispiel kann die Funktion mconcat :: Monoid a => [a] -> a
verwendet werden, um eine Liste von Summen auf einzelne Summe oder eine verschachtelte Liste in eine flache Liste zu reduzieren. Betrachten Sie dies als eine Art Verallgemeinerung von (++)
oder (+)
Operationen, die auf eine Art zwei Dinge "verschmelzen".
A Functor
Ein Funktor in Haskell ist eine Sache, die ganz direkt den Betrieb verallgemeinert map :: (a->b) -> [a] -> [b]
. Anstatt über eine Liste zu mappen, bildet sie über Struktur, wie eine Liste, Binärbaum oder sogar eine IO-Operation. Functors werden wie folgt modelliert:
class Functor f where
fmap :: (a->b) -> f a -> f b
Kontrast diese auf die Definition der normalen map
Funktion.
Ein Applicative Functor
Applicative functors können mit einem generalisierten zipWith
Betrieb wie die Dinge zu sehen. Funktoren ordnen sich zu einem bestimmten Zeitpunkt über allgemeine Strukturen hinweg, aber mit einem Applicative-Funktor können Sie zwei oder mehr Strukturen zusammenfügen. Für die einfachste Beispiel können Sie applicatives zip zusammen zwei ganzen Zahlen innerhalb des Maybe
-Typ:
pure (+) <*> Just 1 <*> Just 2 -- gives Just 3
Beachten Sie, dass die Struktur das Ergebnis zum Beispiel beeinflussen können:
pure (+) <*> Nothing <*> Just 2 -- gives Nothing
Kontrast dieser den üblichen zipWith
Funktion:
zipWith (+) [1] [2]
Statt nur Listen, die applicative Werke für alle Arten von Strukturen. Darüber hinaus verallgemeinert der clevere Trick mit pure
und (<*>)
das Zippen, um mit einer beliebigen Anzahl von Argumenten zu arbeiten. Um zu sehen, wie dies funktioniert, überprüfen Sie die folgenden Arten, während das Konzept der teilweise angewendet Funktionen zur Hand zu halten:
instance (Functor f) => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
Beachten Sie auch die Ähnlichkeit zwischen fmap
und (<*>)
.
A Monad
Monads werden häufig verwendet, verschiedene Rechen Kontexten, wie nicht-deterministisch, oder Seiteneffekt Berechnungen zu modellieren. Da es schon viel zu viele Monad Tutorials gibt, empfehle ich einfach The best one, anstatt noch einen zu schreiben.
In Bezug auf die normalen Listenverarbeitungsfunktionen verallgemeinern Monaden die Funktion concat :: [[a]] -> [a]
, um mit vielen anderen Arten von Strukturen neben Listen zu arbeiten.Als ein einfaches Beispiel, die monadische Operation join
kann abflachen verschachtelte Maybe
Werte verwendet werden:
join (Just (Just 42)) -- gives Just 42
join (Just (Nothing)) -- gives Nothing
Wie dies auf die Verwendung von Monaden als Mittel zur Strukturierung Berechnungen verwendet ist? Betrachten Sie ein Spielzeugbeispiel, bei dem Sie zwei aufeinanderfolgende Abfragen aus einer Datenbank ausführen. Die erste Abfrage gibt Ihnen einen Schlüsselwert zurück, mit dem Sie eine weitere Suche durchführen möchten. Das Problem hierbei ist, dass der erste Wert in Maybe
eingeschlossen ist, so dass Sie nicht direkt damit abfragen können. Statt dessen, wie es vielleicht ein Functor
ist, könnten Sie stattdessen den Rückgabewert mit der neuen Abfrage fmap
. Dies würde Ihnen zwei verschachtelte Maybe
Werte wie oben geben. Eine andere Abfrage würde zu drei Schichten von Maybe
s führen. Dies wäre ziemlich schwierig zu programmieren, aber ein monadischer join
gibt Ihnen eine Möglichkeit, diese Struktur zu glätten, und arbeiten mit nur einer einzigen Ebene von Maybe
s.
(ich glaube, ich werde diesen Posten Bearbeitung viel, bevor es überhaupt Sinn macht ..)
Haben Sie das gelesen [Typeclassopedia] (http://www.haskell.org/haskellwiki/Typeclassopedia)? – dave4420
Vielen Dank für Ihren Rat. Ich hätte es zuerst lesen sollen. – Znatz
[Monaden sind wie Burritos] (http://blog.plover.com/prog/burritos.html). Ja wirklich. –