Ein Einstieg-Projekt, um sich am beste mit den Kombinatoren und den Church-Zahlen auseinander zusetzen, ist Taschenrechner daraus zu bauen.
Link zum lambdafizierten Taschenrechner: Calculator.html
Eine Verkettung der arithmetischen Zahlen und Operationen.
Als Helferfunktion gibt es einen sogenannter CalculatorHandler, mit dem solch eine Verkettung von Konstruktion ermöglichen.
const calculatorHandler = op => n => k => f => f(op(n)(k));
Der calculatorHandler nimmt jeweils eine arithmetische Operation (Addition, Subtraktion, Multiplikation usw.), zwei Werte und zum Schluss eine Funktion entgegen.
Um mit Zahlen zu rechnen reichen die Arithmetischen-Operatoren (+, -, * etc.) von JavaScript:
const plus = n => k => n + k;
const multiplication = n => k => n * k;
const subtraction = n => k => n - k;
const exponentiation = n => k => n ** k;
const division = n => k => n / k;
// example
plus(1)(2) // 3
multiplication(2)(3) // 6
subtraction(5)(2) // 3
Mit dem CalculatorHandler und den Arithmetischen-Operatoren kombiniert, ist es möglich via Point-Freestyle aus den vorhing erstellten Operatoren neue Funktionen zur Berechnung zu erstellen:
const add = calculatorHandler(plus);
const multi = calculatorHandler(multiplication);
const sub = calculatorHandler(subtraction);
const pow = calculatorHandler(exponentiation);
const div = calculatorHandler(division);
Mit der Thrush-Funktion (T = x => f => f(x)
) als den Taschenrechner-Starter und den neuen Operator-Funktionen, ist es mögliche eine unendliche Verkettungen von Zahlen und Operationen zu erstellen.
T(1)(add)(2)(pow)(6)(sub)(2)(div)(8)(add)(7)(multi)(4)(sub)...
Um dieser Verkettung ein Ende zu setzen und das Resultat der Berechnung zu erhalten, benötigt es jeglich die Identitäts-Funktion als Letztes anzuwenden.
T(1)(add)(2)(id) // 3
T(1)(sub)(2)(id) // -1
T(5)(multi)(4)(add)(2)(id) // 22
T(5)(div)(5)(multi)(100)(add)(1)(id) // 101
Um die Leserlichkeit des Code zu verbessern, wird für die Trush- und id-Funktion ein passender Variablename gewählt.
Implementation (Umbenennung):
const calc = T;
const result = id;
Beispiel:
calc(5)(multi)(4)(sub)(4)(pow)(2)(div)(8)(add)(10)(result) // 42
Das der Taschenrechner nicht nur mit JavaScript-Zahlen sondern auch mit Church-Zahlen rechnen kann, braucht es nur die lambdafizierte Arithmetik-Operatoren mit Church-Zahlen mit dem CalculatorHandler zu kombinieren.
const churchAdd = calculatorHandler(churchAddition);
const churchMulti = calculatorHandler(churchMultiplication);
const churchPow = calculatorHandler(churchPotency);
const churchSub = calculatorHandler(churchSubtraction);
Mit diesen lambdafizierte Arithmetik-Operatoren und den Church-Zahlen lässt sich der Taschenrechner gleich bequem bedienen.
calc(n5)(churchMulti)(n9)(churchAdd)(n4)(churchSub)(n7)(result) // n42
Chuch-Zahlen sind Nested-Funktionen und es ist schwer mit blossem Auge zu entziffern welche Zahl sich hinter versteckt. Schon nur die Church-Zahl n7 gibt dir diese Funktion:
f => a => f(f(f(f(f(f(f(a))))))); //n7
Die Hilfe zum die Zahl hinter einer Church-Zahl zu Entziffern ist die Funktion jsNum
jsNum(n42) // 42
Was der lambdafizierter Taschenrechner im vergleich zum JavaScript-Taschenrechner nicht kann sind mit negative Zahlen rechnen, da Church-Zahlen nur Werte der Natürlichen-Zahlen repräsentiert werden kann:
calc(1)(sub)(7)(result) // -6
calc(n1)(churchSub)(n7)(result) // 0 bzw. n0
Gleiches Problem wie mit den negativen Zahlen, können die Church-Zahlen keine Rationale-Zahlen repräsentiere. Deswegen gibt es keinen lambdafizierten Division-Operator.
Bei Berechnung mit grösseren Church-Zahlen und längerer Verkettungen kann es zu einem Maximum call stack size exceeded - Error kommen:
calc(n5)(cpow)(n8)(cmulti)(n6)(cadd)(n8)(csub)(n9) ... // Maximum call stack size exceeded
Um den lambdafizierten Taschenrechner, wie ein gewöhnter Taschenrechner auch visuell bedienen zu können, wurde eine statische HTML-Webseite, mit einem grafischen Taschenrechner und den von hier gezeigten Funktionen implementiert:
Link zum lambdafizierten Taschenrechner: Calculator.html
- Alle Funktionen sind rein
- In allen Funktionen gibt es keine Ausdrücke wie
for
,while
oderdo
Schleifen.