Gestern Nacht hatte ich ziemlich frustriert einen langen Artikel geschrieben, den ich dann aber nochmal überschlafen wollte, weswegen ich ihn zunächst nicht abgeschickt habe. Darin hatte ich versucht ein Problem zu beschreiben, das ich nicht lösen konnte, bzw. ich konnte es zwar lösen, aber der Code war sehr unschön, lang und unübersichtlich. Dabei ging es darum, dass an verschiedenen Stellen in meinem Programm nach und nach eine Struktur aufgebaut werden sollte, wobei der Anfangszustand der Struktur erst nach diesem Prozess festgelegt werden konnte. Ich hatte drei Varianten durchgespielt, alle objektorientiert, die mir alle nicht gefallen haben. Ein paar Stunden Schlaf, etwas googlen und etwas systematisches Denken haben mich dann zu dem Ergebnis geführt, dass das Problem einfach durch Continuations zu lösen ist, und spezifisch durch die Continuation Monade. Diese sieht so aus:
Code: Alles auswählen
def unit(v):
return lambda c: c(v)
def bind(ma, mf):
return lambda c: ma(lambda v: mf(v)(c))
def then(ma, mb):
return lambda v: bind(ma(v), mb)
Code: Alles auswählen
def identity(x):
return x
def add(n):
def adder(x):
return lambda c: c(x + n)
return adder
def double(x):
return lambda c: c(x * 2)
def inc(x):
return lambda c: c(x + 1)
first = add(5)
second = then(first, double)
third = then(second, inc)
compute = bind(unit(5), third)
assert compute(identity) == 21 # (((5 + 5) * 2) + 1) == 21
compute = bind(unit(3), third)
assert compute(identity) == 17 # (((3 + 5) * 2) + 1) == 17
Continuation Passing Style hatte ich schon öfter verwendet, aber die Continuation Monade war mir bisher ein Rätsel. Dann habe ich heute Morgen einen Artikel [Link] gefunden, wo sie für Clojure erklärt wird, und zwar viel besser, als ich es könnte. Python ist ja so eine Art Lisp mit Syntax, deswegen war der Code sehr einfach zu übertragen. Nur die then() Funktion stammt von mir, es ist die rechte Hälfte der rechten Seite des monadischen Assoziativgesetzes:
Code: Alles auswählen
bind(bind(unit(v), f), g) == bind(unit(v), lambda x: bind(f(x), g))