Writer-Monade — eine Monade, die neben dem eigentlichen Ergebnis einen zusätzlichen Ausgabewert akkumuliert, ohne Seiteneffekte zu erzeugen. Sie eignet sich für Protokollierung, Audit-Trails oder das Sammeln von Warnungen, wenn der Log selbst ein Wert der Berechnung ist.
Die Idee: Ergebnis plus Log
Eine Berechnung in der Writer-Monade liefert ein Paar: den eigentlichen Wert a und ein angesammeltes Protokoll w. Das Protokoll wird mit der Operation mappend eines Monoids kombiniert — einer mathematischen Struktur mit einer assoziativen Verknüpfung und einem neutralen Element (für Listen ist das die Verkettung mit der leeren Liste als neutralem Element). Dadurch bleibt die gesamte Akkumulation rein: nichts wird global verändert, jede Stufe der Kette reicht den bisherigen Log an die nächste weiter.
newtype Writer w a = Writer { runWriter :: (a, w) }
Der Kern ist damit fast derselbe wie bei der State-Monade — nur dass der weitergereichte Wert nicht verändert, sondern nur angehängt wird.
tell und Freunde
Die zentrale Funktion ist tell :: Monoid w => w -> Writer w (): Sie hängt einen Eintrag an das Protokoll an. Der Wert des Ergebnisses ist (), die Bedeutung steckt im Log. Beim Ausführen wählt man, was man braucht:
runWriter— liefert Paar(Wert, Log)execWriter— nur der Log (häufigster Fall)evalWriter— nur der Wertlisten— Zugriff auf den Zwischenstand des Logs innerhalb der Berechnungpass— den Log einer Teilberechnung nachträglich verändern
Als Monoid eignen sich Listen (eine Liste von Log-Zeilen), Strings, Mengen oder selbstgebaute Summenwerte — etwa Zähler, die durch die Verknüpfung addiert werden. Damit lassen sich ohne eine einzige mutable Variable Kennzahlen wie „wie viele Validierungen liefen fehlerhaft“ sammeln.
Wo die Writer-Monade passt — und wo nicht
Stärken: Sie macht Logs typsicher und referenziell transparent, ist leicht testbar und trägt keine globale Logging-Instanz. Sie ist die pure Alternative, wenn man in einer reinen Funktion nebenbei protokollieren will.
Grenzen: Bei sehr großen Protokollen hält die Writer-Monade die gesamte Ausgabe im Speicher (sie kann den Log nicht vorzeitig leeren) und die Listen-Verkettung kann schlecht assoziieren. Für echte Laufzeit-Logs in Produktivsystemen nutzt man deshalb einen dedizierten Logger; die Writer-Monade ist das Werkzeug für kompakte, rein funktionale Ausgaben — etwa als WriterT-Schicht im Transformer-Stack, siehe Monadentransformer.
Verwandte Grundlagen: Monade, Funktionale Programmierung, Funktionskomposition, IO-Monade, Haskell-Befehle.