9 Punkte von bboydart91 2026-02-08 | Noch keine Kommentare. | Auf WhatsApp teilen

Text

  • Erklärt anhand von TypeScript-Code den Weg von zwei Problemen, die sich allein mit map bei Funktoren nicht lösen lassen (in einem Container eingeschlossene Funktionen und verschachtelte Kontexte bei Komposition), bis hin zu applikativen Funktoren und Monaden
  • Beginnt mit dem Hintergrund, dass Eugenio Moggi 1988 Programme nicht als A → B, sondern als A → T(B) modellierte
  • Behandelt die Struktur flatMap = map + join und die drei Gesetze für ihre sichere Verwendung (Assoziativität, linke Einheit, rechte Einheit)
  • Erklärt, warum die Monade ein „Monoidobjekt in der Kategorie der Endofunktoren“ ist, im Vergleich zum Monoid der Ganzzahladdition
  • Erwähnt auch, warum Promise zwar monadisch funktioniert, aber keine strenge mathematische Monade ist

Die Grenzen von Funktoren: Was mit map nicht geht

  • Wendet man eine gecurryte Funktion mit map an, landet das Ergebnis als Funktion im Container, etwa Maybe<(b: number) => number>
    • map kann nur Funktionen außerhalb des Containers entgegennehmen, daher gibt es keine Möglichkeit, eine darin eingeschlossene Funktion auf einen anderen Wert anzuwenden
  • Komponiert man zwei Funktionen, die selbst wieder einen Funktor zurückgeben, verschachtelt sich der Kontext zu etwas wie Maybe<Maybe>
    • Mit jedem zusätzlichen Schritt wächst das zu einer unendlichen Verschachtelung wie Maybe<Maybe<Maybe<...>>>

Applikative Funktoren: Funktionen im Container anwenden

  • Mit der Operation apply lässt sich eine im Container eingeschlossene Funktion auf den Wert eines anderen Containers anwenden
    • apply: T<(A → B)> → T<A> → T<B>
  • Mit der Operation pure wird ein reiner Wert in den Container eingefügt
  • Grenze: Es muss im Voraus feststehen, welche Container komponiert werden
    • Dynamische sequenzielle Abhängigkeiten, bei denen die nächste Berechnung vom Ergebnis der vorherigen abhängt, lassen sich damit nicht ausdrücken

Monaden: Die Erfindung einer Operation zum Entschachteln

  • Die Operation join faltet einen doppelten Container T<T<A>> zu T<A> zusammen
    • Array.prototype.flat in JavaScript übernimmt dieselbe Rolle
  • In der Praxis verwendet man flatMap, das map und join kombiniert
    • flatMap: T<A> → (A → T<B>) → T<B>
    • map nimmt A → B entgegen, flatMap dagegen A → T<B> und hält das Ergebnis dadurch auf einer Ebene

Die drei Gesetze von flatMap

  • Assoziativgesetz: Beim Entschachteln einer dreifachen Verschachtelung T(T(T(A))) muss das Ergebnis gleich sein, egal ob man zuerst innen oder außen entfaltet
    • m.flatMap(f).flatMap(g) === m.flatMap(x => f(x).flatMap(g))
  • Gesetz der linken Einheit: Wenn man einen Wert mit pure einfügt und sofort flatMap anwendet, ist das dasselbe wie die Funktion direkt anzuwenden
    • pure(a).flatMap(f) === f(a)
  • Gesetz der rechten Einheit: Übergibt man pure an flatMap, bleibt der ursprüngliche Container unverändert
    • m.flatMap(pure) === m

Zerlegung von „Monoidobjekt in der Kategorie der Endofunktoren“

  • Funktoren in der Programmierung gehen von der Typwelt in die Typwelt und sind daher Endofunktoren
  • Man kann eine Kategorie der Endofunktoren bilden, in der die Endofunktoren selbst die Objekte sind
  • Setzt man darauf die Anforderungen eines Monoids an (binäre Operation + Assoziativgesetz + neutrales Element), ergibt sich:
    • binäre Operation = join
    • neutrales Element = pure
    • Die Struktur entspricht exakt dem Monoid der Ganzzahladdition

Warum Promise keine Monade ist

  • then verarbeitet abhängig vom Rückgabewert eine Mischung aus map und flatMap
  • Ein Zustand vom Typ Promise<Promise> ist zur Laufzeit nicht erlaubt und wird sofort zu einer einzigen Ebene zusammengeführt
  • Das ist in der Praxis bequem, erfüllt aber nicht die mathematischen Monadengesetze

Noch keine Kommentare.

Noch keine Kommentare.