chain
MethodeWarum benötigt die Fantasy-Landespezifikation, dass die Kette einen Wert derselben Kette zurückgeben muss?Ein Wert, die eine Kette hat, muß ein
chain
Verfahren bereitzustellen. Die Kette Verfahren ein Argument nimmt:
m.chain(f)
f
muss eine Funktion sein, die
- einen Wert zurückgibt Wenn
f
nicht eine Funktion ist, ist das Verhalten vonchain
unspezifiziert.f
muss einen Wert von derselben Kette zurückgebenchain
muss einen Wert von derselben Kette zurückgeben
Gegeben ist eine einfache Implementierung der Option Monade:
// prototypes:
const someProto = {
of(x) { return some(x) },
map(f) { return some(f(this.x)) },
ap(ftor) { return ftor.map(this.x) },
join() { return this.x },
chain(mf) { return this.map(mf).join() }
};
const noneProto = {
of() { return this },
map() { return this },
ap() { return this },
join() { return this },
chain() { return this }
};
// factories:
function some(x) {
return Object.assign(Object.create(someProto), {x: x});
}
function none() {
return Object.assign(Object.create(noneProto), {x: null});
}
Um zu garantieren, dass chain
immer eine Option monad zurückgibt, müsste ich sicherstellen, dass (monadische Funktion) immer eins zurückgibt. Dies ist nicht möglich, da nicht Teil der Implementierung ist. Vielmehr ist es definiert, wenn das monadisch verwendet:
// auxiliary function:
const sub = y => x => x - y;
let a = some(2);
let b = some(3);
a.chain(x => b.chain(y => some(sub(x)(y)))); // {x: 1}
a.chain(x => b.chain(y => sub(x)(y))); // 1 - ouch!
Bei der zweiten Methode übergab Anwendung die Funktion gibt keinen monadisch, die zu einem ausgepackten Ergebnis der monadischen Berechnung führt. Ich könnte einen Typcheck zu chain
oder join
vielleicht durch Ente eingeben, um das Problem zu lösen - das wäre aber ziemlich hässlich.
Warum benötigt die Spezifikation an dieser Stelle Typensicherheit? Javascript wird dynamisch typisiert, und ich würde lieber geeignete Komponententests schreiben, anstatt Typprüfungen zur Laufzeit durchzuführen. Würde ich dann die Spezifikation verletzen?
Das Problem ist, wenn jemand diese Option Implementierung in einer Weise missbraucht, die ich in meinem zweiten Beispiel tat, verletzt es die Spezifikation. Daher könnte meine Implementierung nicht mit Fantasy-Land konform sein. Die einzige Möglichkeit, dies zu verhindern, besteht offenbar darin, zur Laufzeit eine Typprüfung hinzuzufügen. Ich glaube, das ist irgendwie hässlich. – ftor
Ihre Implementierung einer Option monad ist kompatibel mit der Spezifikation. Ihre Verwendung von '.chain() 'ist nicht. Von Benutzern Ihrer Chainable wird erwartet, dass sie die entsprechende Methode verwenden - entweder '.chain()' oder '.map()', je nachdem, welche Funktion sie bereitstellen. – ErikR
OK, ich bin nicht ganz überzeugt, aber akzeptiere die Antwort, danke! – ftor