关闭。这个问题需要更多focused .它目前不接受答案。
想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post .
3年前关闭。
Improve this question
JavaScript 中的函数式编程是否可以具有任何类型的多态性?
我喜欢 FP,但是当我想使用 JS 时,除了使用类/原型(prototype)之外,我无法弄清楚如何在 JS 中支持多态性。
例如如何实现 toString
在 JS 中使用 FP?
使用 OOP 我可以简单地重载 toString
以便 object.toString()
执行特定于 object
的 toString 代码或者它的原型(prototype)。
最佳答案
Javascript 是一种无类型语言
不,Javascript 没有多态的概念,因为它是一种无类型语言。简单地说,多态意味着严格的类型系统在受控条件下不那么严格,也就是说它不会因多态行为而失去类型安全性。
不过,无类型语言稍微简化了一些。从静态类型系统的 Angular 来看,Javascript 有一个巨大的联合类型,一个值或其底层表达式可以在运行时采用其任何表示形式(变量甚至可以在其存在期间适应不同的类型)。这种类型也称为动态类型。
动态类型语言具有自省(introspection)功能,可以在运行时检查值的类型。但这种手段是有限的。例如,你不能内省(introspection)函数的类型,只要它没有被完全应用。
然而,原始意义上的函数式编程意味着使用许多小的、专门的一阶和高阶函数,这些函数在 curried form 中声明。 .这种方法会导致在您的代码中部分应用函数。现在的问题是,您不仅要推断初始函数的类型,还要推断部分应用函数的中间类型。这将很快变得艰难:
// what's the type of this function?
const comp = f => g => x => f(g(x));
// and this partially applied one?
const inc = n => n + 1;
comp(inc);
// and even worse:
comp1 = comp(comp);
comp2 = comp(comp) (comp);
我敢肯定我已经把你弄丢了。从头脑中推断出这些类型需要很多时间。作为一名开发人员,你真的应该像编译器一样工作吗?我不这么认为。
问题的替代解决方案
幸运的是,Javascript 社区一直在积极开发此类问题的解决方案。
语言之上的静态类型检查器
Flow 和 TypeScript 是静态类型检查器,它们尝试向 Javascript 追溯添加类型系统。我个人不认为这是一种有前途的方法,因为通常在创建新语言时首先设计类型系统。 Javascript 几乎可以在任何地方执行副作用,这使得创建一个健全且可靠的类型检查器变得非常困难。查看 issues在 Flow 存储库中获取您自己的图片。
将 Javascript 降级为编译目标
是的,这个标题可能有点基于意见,但这就是我的感觉。 Elm、purescript、Facebook 的 Reason 是这种方法的代表。好吧,如果你想放弃 Javascript,这些都是合理的可能性。但是该赌哪匹马呢? Javascript 生态系统的碎片化真的是可取的吗?还是我们想要一个依赖像 Facebook 这样的供应商的社区?我真的不能回答这个问题,因为我有很大的偏见,正如你即将看到的。
运行时类型检查器
注意:这是无耻的插件!
作为一种动态类型语言,Javascript 具有成熟的自省(introspection)能力。除了 ES2015 代理之外,我们还拥有构建虚拟化运行时类型检查器所需的一切。在这种情况下,虚拟意味着它是可插拔的,即您可以打开和关闭它。运行时类型系统需要是可插拔的,因为它对性能有重大影响,并且仅在开发阶段才需要。
几个月以来,我一直在研究这样的类型检查器,到目前为止,这是一段令人兴奋的旅程。 ftor远非稳定,但我相信这种方法值得探索。
这是
comp
上面的组合器作为带有类型提示的类型化版本( TS
只是一个内部 Symbol
,它保存了类型的当前签名,您可以使用它来请求此签名以进行调试):import * as F from ".../ftor.js";
F.type(true);
const comp = F.Fun(
"(comp :: (b -> c) -> (a -> b) -> a -> c)",
f => g => x => f(g(x))
);
const inc = F.Fun(
"(inc :: Number -> Number)",
n => n + 1
);
comp(inc) [TS]; // "(comp :: (a -> Number) -> a -> Number)"
const comp1 = comp(comp),
comp2 = comp(comp) (comp);
comp1 [TS]; // "(comp :: (a -> b0 -> c0) -> a -> (a0 -> b0) -> a0 -> c0)"
comp2 [TS]; // "(comp :: (b1 -> c1) -> (a0 -> a1 -> b1) -> a0 -> a1 -> c1)"
comp1
的中间类型签名告诉您它期望...那就是你会像
comp1(inc) (1) (add) (2) (3)
一样应用它.comp2
的中间类型签名告诉您它期望...你会像
comp2(inc) (add) (2) (3)
一样应用它.所以comp2
实际上很有用,因为它允许我们应用二元函数作为组合的内部函数。诚然,如果您不熟悉这些类型签名,就不容易阅读它们。但根据我的经验,学习曲线相当短。
ftor 支持参数和行多态,但目前不是特别的。
关于javascript - JavaScript 中的函数式编程是否可以具有任何类型的多态性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48257447/