关于函数编程:混合Erlang和Haskell

Mixing Erlang and Haskell

如果您已经了解了函数式编程范式,那么您可能会同时喜欢Erlang和Haskell。两者都具有纯粹的功能核心和其他优点,例如轻量级线程,使它们非常适合多核世界。但也有一些不同。

Erlang是一种经过商业验证的容错语言,具有成熟的分布模型。它在运行时通过热代码加载来升级其版本方面有一个看似独特的功能。(酷!)

另一方面,haskell拥有任何主流语言中最复杂的类型系统。(我将"主流"定义为任何出版过O'Reilly书籍的语言,所以haskell很重要。)它的直线单线程性能看起来比Erlang更好,它的轻量级线程也更轻。

我正试图为我的代码生命的剩余时间构建一个开发平台,我想知道是否可以将Erlang和Haskell混合在一起以实现一个最佳的平台。这个问题有两部分:

  • 我想使用Erlang作为一种容错MPI,将GHC运行时实例粘合在一起。每个GHC运行时将有一个Erlang进程。如果"不可能的事情发生了",并且GHC运行时死了,那么Erlang进程会以某种方式检测到这一点,然后也死了。Erlang的热代码加载和分发功能将继续工作。可以将GHC运行时配置为仅使用一个核心,或本地计算机上的所有核心,或两者之间的任何组合。一旦编写了Erlang库,其余的Erlang级别代码应该是纯样板文件,并根据每个应用程序自动生成。(例如,通过haskell DSL)一个人如何至少实现其中的一些事情?
  • 我希望二郎和哈斯克尔能够分享同一个Garabage收藏家。(这是一个比1更进一步的想法。)在JVM和CLR上运行的语言通过共享运行时实现了更大的质量。我了解在JVM或CLR上运行erlang(热代码加载)和haskell(更高级的多态性)存在技术限制。但是,把垃圾收集器拆开怎么样?(类似于函数语言运行时的开始。)很明显,分配仍然必须非常快,因此可能需要静态地链接该位。而且应该有一些机制来区分可变堆和不可变堆(包括惰性的一次性写入内存),因为GHC需要这样做。修改HIPE和GHC以便垃圾收集器可以共享一个堆是否可行?
  • 请以任何经验(正面或负面)、想法或建议回答。事实上,任何反馈(没有直接的滥用!)欢迎。

    更新

    感谢所有的4个回复-每个都教给我至少一个有用的东西,我不知道。

    关于剩下的编码生活的事情-我稍微把它放在嘴边,以引起争论,但它实际上是真的。有一个项目我一直在想,我打算工作到我死,它需要一个稳定的平台。

    在我上面提出的平台中,我只编写haskell,因为样板文件erlang将自动生成。那么哈斯克尔会持续多久呢?好吧,Lisp仍然和我们在一起,看起来不会很快消失。Haskell是BSD3开源软件,已经达到临界质量。如果编程本身在50年内仍然存在,我希望haskell,或者haskell的一些持续进化,仍然会出现在这里。

    更新2以响应rvirding的帖子

    同意-实现一个完整的"Erskell/Haslang"通用虚拟机可能并非绝对不可能,但这确实非常困难。共享垃圾收集器级别就像虚拟机一样,虽然仍然很困难,但对我来说,这听起来不那么困难。在垃圾收集模型中,函数语言必须有很多共同点——不可变数据(包括thunk)的不公平性和快速分配的要求。因此,公共性与单片虚拟机紧密捆绑在一起似乎有点奇怪。

    虚拟机确实有助于达到临界质量。看看像f和scala这样的"lite"功能语言是如何发展起来的。scala可能没有Erlang的绝对容错能力,但它为许多绑定到JVM的人提供了一条逃生路线。

    While having a single heap makes
    message passing very fast it
    introduces a number of other problems,
    mainly that doing GC becomes more
    difficult as it has to be interactive
    and globally non-interruptive so you
    can't use the same simpler algorithms
    as the per-process heap model.

    当然,我完全理解。GHC开发团队中非常聪明的人似乎正试图通过一个并行的"停止世界"GC来解决部分问题。

    http://research.microsoft.com/en-us/um/people/simonpj/papers/parallel-gc/par-gc-ismm08.pdf

    (很明显,"停止世界"不会飞到通用的Erlang,因为它的主要用例。)但即使在"停止世界"正常的用例中,它们的加速也不会出现在


    很多Haskell和Erlang的人对Erlang管理分布的模型很感兴趣,而Haskell并行运行共享内存节点来处理所有的数字处理/逻辑。

    从haskell-erlang库开始:http://hackage.haskell.org/package/erlang

    我们在Ruby Land也有类似的努力,通过傲慢:http://github.com/mworton/hubris/tree/master

    现在的问题是找到一个真正推动erlang/haskell互操作的人来发现棘手的问题。


    虽然这是一个相当古老的线程,但如果读者仍然感兴趣,那么值得一看CloudHaskell,它将Erlang风格的并发性和分发带给GHC稳定。

    即将发布的分布式过程平台库增加了对OTP风格结构的支持,如gen_服务器、监督树和从Erlang/OTP借来并受其启发的各种其他"haskell风格"抽象。


    在Haskell和Erlang之间混合GC会很有趣。Erlang使用每个进程堆并在进程之间复制数据——因为Haskell甚至没有进程的概念,所以我不确定如何在两个进程之间映射这个"通用"GC。此外,为了获得最佳性能,Erlang使用了各种分配程序,每种分配程序的行为都稍作调整,我确信这会影响GC子系统。

    和软件中的所有东西一样,抽象也是有代价的。在这种情况下,我更怀疑您必须引入这么多层,才能使两种语言克服阻抗不匹配的问题,最终得到一个性能不太好(或有用)的通用VM。

    底线——接受差异!不在同一个过程中运行所有东西有很大的好处,特别是从可靠性的角度来看。另外,我认为期望一种语言/vm在你的余生中持续下去(除非你计划在a.)活得很短或b.)成为某种只在一个项目上工作的代码修道士有点幼稚。软件开发都是关于心智的敏捷性,并且愿意使用最好的可用工具来构建快速、可靠的代码。


    正如Dizzyd在他的评论中提到的,并不是所有消息中的数据都被复制,大型二进制文件存在于进程堆之外,并且不被复制。

    使用不同的内存结构来避免每个进程有单独的堆是完全可能的,并且已经在许多早期的实现中完成了。虽然只有一个堆会使消息传递非常快,但它还引入了许多其他问题,主要是GC变得更加困难,因为它必须是交互式的、全局不中断的,因此您不能使用与每个进程堆模型相同的更简单算法。

    只要我们使用的数据结构是不可变的,那么健壮性和安全性就没有问题。决定使用哪种内存和GC模型是一个很大的权衡,不幸的是,这里普遍存在最好的模型。

    虽然haskell和erlang都是功能语言,但它们在许多方面都是非常不同的语言,并且实现方式也非常不同。很难想出一个能有效处理两种语言的"Erskell"(或Haslang)机器。我个人认为最好把它们分开,确保它们之间有一个很好的接口。


  • 您可以使用otp gen_supervisor进程来监视使用open_port()生成的haskell实例。根据"端口"的退出方式,您可以重新启动它或决定它是故意停止的,并让相应的Erlang进程也停止。

  • 福格达布伊特。即使您所说的这些独立于语言的虚拟机有时也会在语言之间传递数据时遇到问题。您应该以某种方式序列化这两者之间的数据:数据库、XML-RPC之类的。

  • 顺便说一下,在你的余生中建立一个平台的想法也可能是不切实际的。计算技术和时尚的变化太频繁了,以至于你不能一直只使用一种语言。你的问题就是:没有一种语言能做到我们所希望的一切,即使是今天。


    clr支持使用显式tail操作码(如f所用)进行尾调用优化,而jvm没有(还没有)等效的操作码,这限制了这种语言风格的实现。使用单独的AppDomain允许clr进行热交换代码(参见本博客文章,展示如何进行热交换代码)。

    西蒙·佩顿·琼斯(Simon Peyton Jones)与微软研究公司(Microsoft Research)的F团队一起沿着走廊工作,如果我们最终没有看到具有某种官方地位的铁哈斯克尔(Ironhaskell),那将是一个巨大的失望。Ironerlang将是一个有趣的项目——最大的工作可能是移植绿色线程调度程序,而不必像Windows工作流引擎那样重量级,或者必须在clr上运行beam-vm。