函数编码类型(即嵌套柯里化函数)在 Javascript 中有一些缺点:
- 它们在开发控制台中的表示是模糊的(例如
[Some(5), None]
显示为[f, f]
) - 没有什么能阻止您将组合器应用于错误的类型(例如
eitherMap(f) (Some(5))
) - 你不能检查他们的自由变量
- 你甚至不能躲避打字
这些缺点使它们在现实世界的应用中毫无用处。
我想知道是否有办法克服这些缺点并想出了以下草图:
const tag = (name, x, k) => {
const Cons =
Function(`return function ${name}() {}`) ();
Cons.prototype[Symbol.toStringTag] = name;
Cons.prototype["run" + name] = k;
Cons.prototype.tag = name;
const o = new Cons();
Object.defineProperty(o, "value", {get: () => x});
return o;
};
const Some = x =>
tag("Option", x, def =>
tag("Option", x, k => k(x)));
const None = tag("Option", null, def =>
tag("Option", def, k => def));
const option = def => k => fx =>
fx.runOption(def).runOption(k);
const safeInc = option(0) (n => n + 1);
safeInc(Some(5)); // 6
safeInc(None); // 0
const xs = [Some("foo"), None]; // [Option, Option]
/*
expanded dev console display:
1: Option {value: ...} --> expands to "foo"
2: Otpion {value: ...} --> expands to null
*/
请注意,我对原型继承根本不感兴趣。
这种方法既乏味又可能很慢,因为我应用了Function
构造函数,这使得代码更难预测。有没有更好的方法给 curried 函数一个类型(或者更确切地说是 JS 中的标签),以便消除列出的缺点?