如果你已经接受了函数式编程范式,那么你很可能同时喜欢 Erlang 和 Haskell。两者都具有纯功能内核和其他优点,例如轻量级线程,使其非常适合多核世界。但也有一些不同之处。
Erlang 是一种经过商业验证的容错语言,具有成熟的分布模型。它具有一个看似独特的功能,即通过热代码加载在运行时升级其版本的能力。(太酷了!)
另一方面,Haskell 拥有所有主流语言中最复杂的类型系统。(我将“主流”定义为任何有出版 O'Reilly 书籍的语言,因此 Haskell 很重要。)它的直线单线程性能看起来优于 Erlang 的,它的轻量级线程看起来也更轻。
我正在尝试为我余下的编码生涯构建一个开发平台,并且想知道是否可以混合 Erlang 和 Haskell 来实现最佳的平台。这个问题有两个部分:
- 我想使用 Erlang 作为一种容错 MPI 来将 GHC 运行时实例粘合在一起。每个 GHC 运行时将有一个 Erlang 进程。如果“不可能的事情发生了”并且 GHC 运行时死了,那么 Erlang 进程会以某种方式检测到这一点并且也会死掉。Erlang 的热代码加载和分发功能将继续工作。GHC 运行时可以配置为仅使用一个内核,或本地计算机上的所有内核,或两者之间的任何组合。一旦编写了 Erlang 库,其余的 Erlang 级别代码应该是纯粹的样板文件,并在每个应用程序的基础上自动生成。(例如,可能通过 Haskell DSL。)如何实现至少其中的一些?
- 我希望 Erlang 和 Haskell 能够共享同一个垃圾收集器。(这比 1 更进一步。)在 JVM 和 CLR 上运行的语言通过共享运行时实现了更大的质量。我了解在 JVM 或 CLR 上运行 Erlang(热代码加载)和 Haskell(更高种类的多态性)存在技术限制。但是如果只拆分垃圾收集器呢?(有点像函数式语言运行时的开始。)分配显然仍然必须非常快,所以可能需要静态链接该位。并且应该有一些机制来区分可变堆和不可变堆(包括惰性写入一次内存),因为 GHC 需要这个。修改 HIPE 和 GHC 以便垃圾收集器可以共享一个堆是否可行?
请回答任何经验(正面或负面)、想法或建议。事实上,任何反馈(没有直接滥用!)都是受欢迎的。
更新
感谢迄今为止所有 4 条回复——每条回复都至少教会了我一件我不知道的有用的事情。
关于编码生活的其余部分-我将其包括在面颊上以引发辩论,但实际上是真的。我有一个项目,我打算一直工作到我死,它需要一个稳定的平台。
在我上面提出的平台中,我只会写 Haskell,因为样板 Erlang 会自动生成。那么 Haskell 会持续多久呢?好吧,Lisp 仍然在我们身边,而且看起来它不会很快消失。Haskell 是 BSD3 开源并已达到临界质量。如果编程本身在 50 年后仍然存在,我希望 Haskell 或 Haskell 的一些持续发展仍然存在。
更新 2 以响应 rvirding 的帖子
同意——实现一个完整的“Erskell/Haslang”通用虚拟机可能不是绝对不可能的,但确实非常困难。仅将垃圾收集器级别共享为类似于 VM 的东西,虽然仍然很困难,但对我来说听起来要困难一个数量级。在垃圾收集模型中,函数式语言必须有很多共同点——不可变数据(包括 thunk)的不普遍性以及对快速分配的要求。因此,将通用性与单体 VM 紧密捆绑在一起的事实似乎有点奇怪。
虚拟机确实有助于实现临界质量。看看像 F# 和 Scala 这样的“精简”函数式语言是如何起飞的。Scala 可能没有 Erlang 的绝对容错能力,但它为许多与 JVM 相关联的人提供了一条逃生路线。
虽然拥有单个堆使得消息传递速度非常快,但它引入了许多其他问题,主要是进行 GC 变得更加困难,因为它必须是交互式且全局非中断的,因此您不能使用与 per- 相同的更简单算法进程堆模型。
绝对,这对我来说很有意义。GHC 开发团队中非常聪明的人似乎正试图通过并行的“stop the world”GC 解决部分问题。
http://research.microsoft.com/en-us/um/people/simonpj/papers/parallel-gc/par-gc-ismm08.pdf
(显然“停止世界”对于一般 Erlang 的主要用例来说是行不通的。)但即使在“停止世界”可以使用的用例中,它们的加速似乎也不是普遍的。所以我同意你的看法,不太可能有一个普遍最好的 GC,这就是我在我的问题的第 1 部分中指定的原因
GHC 运行时可以配置为仅使用一个内核,或本地计算机上的所有内核,或两者之间的任何组合。
这样,对于给定的用例,我可以在基准测试之后选择采用 Erlang 方式,并运行一个 GHC 运行时(使用单线程 GC)加上每个内核一个 Erlang 进程,并让 Erlang 在内核之间复制内存以获得良好的局部性.
或者,在双处理器机器上,每个处理器有 4 个内核,处理器上有良好的内存带宽,基准测试可能建议我运行一个 GHC 运行时(使用并行 GC)加上每个处理器一个 Erlang 进程。
在这两种情况下,如果 Erlang 和 GHC 可以共享一个堆,那么共享可能会以某种方式绑定到在单个内核上运行的单个 OS 线程。(我在这里超出了我的深度,这就是我问这个问题的原因。)
我还有另一个议程——独立于 GC 对功能语言进行基准测试。我经常阅读 OCaml v GHC v Erlang v 的基准测试结果......并且想知道不同的 GC 混淆了多少结果。如果 GC 的选择可以与函数式语言的选择正交怎么办?GC到底有多贵?看到这个魔鬼倡导者博客文章
http://john.freml.in/garbage-collection-harmful
由我的 Lisp 朋友 John Fremlin 撰写,他很迷人地给出了他的帖子标题“自动垃圾收集是垃圾”。当约翰声称 GC 很慢并且没有真正加速时,我希望能够用一些数字来反驳。