Haskell是一种托管语言吗?

时间:2012-05-30 03:35:29

标签: haskell ghc

我是Haskell的新手。总是让我感到困惑的一件事是Haskell是一个托管(从MS借来的术语)语言(如Java)还是像C这样的编译到本机代码的模糊性?

GHC页面说明“GHC将Haskell代码直接编译为本机代码或使用LLVM作为后端”。

在“编译为本机代码”的情况下,如果没有像JVM这样的东西,垃圾收集等功能是如何实现的?

/ 更新 /

非常感谢您的回答。从概念上讲,您可以帮助指出我对Haskell中垃圾收集的以下哪些理解是正确的:

GHC将Haskell代码编译为本机代码。在编译处理中,垃圾收集例程将被添加到原始程序代码中吗?

OR

有一个程序与Haskell程序一起运行以执行垃圾收集?

5 个答案:

答案 0 :(得分:19)

据我所知,术语“托管语言”专门指的是一种针对.NET /公共语言运行时的语言。所以不,Haskell不是托管语言,也不是Java。

关于Haskell编译的内容:正如您引用的文档所述,GHC将Haskell编译为本机代码。它可以通过直接发出本机代码或首先发出LLVM代码,然后让LLVM将其编译为本机代码来实现。无论哪种方式,运行GHC的最终结果都是本机可执行文件。

除了GHC之外,还有Haskell的其他实现 - 最值得注意的是Hugs,它是一个纯粹的解释器,永远不会生成可执行文件(本机或其他)。

  

如果没有类似JVM的东西,垃圾收集等功能怎么可能?

与JVM一样可行:每次分配内存时,都会向垃圾收集器注册。然后垃圾收集器不时运行,遵循给定的垃圾收集算法的步骤。 GHC编译的代码使用分代垃圾收集。


回复您的修改:

  

GHC将Haskell代码编译为本机代码。在编译处理中,垃圾收集例程将被添加到原始程序代码中吗?

基本上。除了说“将垃圾收集程序添加到原始程序代码中”可能会描绘错误的图片。 GC例程只是每个Haskell程序链接的库的一部分。编译后的代码只包含在适当位置对这些例程的调用。

基本上,每次调用malloc时都要调用GC的alloc函数。

只需查看任何用于C的GC库以及如何使用它:您需要做的就是#include库的头和链接库,并用GC库的alloc函数替换malloc的每个出现(并删除所有调用free)和bam,你的代码被垃圾收集。

  

有一个程序与Haskell程序一起运行以执行垃圾收集吗?

没有

答案 1 :(得分:13)

  

Haskell是否是一个托管(从MS借用的术语)语言,如Java

GHC编译的程序包括垃圾收集器。 (据我所知,Haskell的所有实现都包含垃圾收集,但这不是规范的一部分。)

  

或像C?

这样的编译到本机的代码

GHC编译的程序被编译为本机代码。拥抱解释程序,不编译为本机代码。还有其他几种实现,据我所知,它们都编译为本机代码,但我单独列出这些实现,因为我对这一事实并不那么自信。

  

在“编译为本机代码”的情况下,如果没有像JVM这样的东西,垃圾收集等功能是如何实现的?

GHC编译的程序包括一个运行时系统,它提供了一些基本功能,如M-to-N绿色线程,垃圾收集和IO管理器。从某种意义上说,这有点像“像JVM一样”,因为它提供了许多相同的功能,但它在实现上有很大的不同:所有架构都没有通用的字节码(因此没有“虚拟机”)

  

我对Haskell中垃圾收集的以下理解之一是正确的:

     
      
  1. GHC将Haskell代码编译为本机代码。在编译处理中,垃圾收集例程将被添加到原始程序代码中吗?
  2.   
  3. 有一个程序与Haskell程序一起运行以执行垃圾收集吗?
  4.   

案例1是正确的:在编译期间,运行时系统代码被添加到程序代码中。

答案 2 :(得分:4)

“托管语言”是一个重载的术语,所以这里是一个单词的答案,然后是(我)脑海中常见的不同含义的一些细节:

在CLR目标中管理

,Haskell无法编译到Microsoft CLI的IL 好吧,我读到有一些解决方案可以这样做,但是imo,不要...... CLR不是为FP构建的,并且会严重缺乏优化,可能会产生研究语言性能。如果我个人真的想要定位CLR,我会使用F# - 它不是不是一种功能语言,但它很接近。

N.B。这是术语“托管语言”的最准确和实际意义。接下来的意思是错误的,但不过不幸的是很常见。

管理为自动垃圾收集

,这几乎是必须的。我的意思是,超出规范:如果我们不得不进行垃圾收集,它将破坏使我们在高海拔地区工作的功能主题,这是我们心爱的家。

它还会强制执行杂质和记忆模型。

管理为编译为由VM运行的字节码

否(通常)
这取决于你的后端: 不仅我们今天有不同的Haskell编译器,一些编译器有不同的后端 - 甚至还有JavaScript的后端!

因此,如果您确实想要定位VM,则可以使用现有/后端来实现它。但是Haskell不会要求它。因此,就像您可以编译为原生的原始金属二进制文件一样,您可以编译为其他任何内容。

与C# 1 ,VB.NET等CLR语言形成鲜明对比,与Java等不同,您不必定位JVM,即CLR ,单声道等,因为Haskell根本不会要求一个VM。

GHC就是一个很好的例子。当您在GHC中编译时,它不会直接编译为二进制文件,它会编译为一个名为Core的中间语言,然后在进入另一种名为STG的语言之前从Core到Core优化一段时间,然后才进入代码生成(如果你告诉它可以停在那里)。 2 这些天你也可以用它来编译成LLVM字节码(这需要进行一些很棒的优化)。使用LLVM后端,GHC可以生成狂野更快的程序。有关它和GHC后端的更多信息,请转到here

下图说明了GHC编译管道,here您可以找到有关各个阶段的更多信息。

The GHC compilation pipeline

查看底部的叉子是否有三个不同的目标?那些是我所指的后端。


1 未来的异常和有趣的事实:Microsoft目前正在开发本机.NET!狡猾地命名为:Microsoft .NET Native

答案 3 :(得分:1)

对于您来说,“托管语言”的定义特征是什么?短语“GHC将Haskell代码直接编译为本机代码或使用LLVM作为后端”,你引用的内容非常清楚GHC的作用,所以我怀疑那些让你感到困惑的“含糊不清”更像是“托管语言” “而不是GHC的文档。

  

在“编译为本机代码”的情况下,如果没有像JVM这样的东西,垃圾收集等功能是如何实现的?

您认为“像JVM这样的东西”如何实现垃圾收集等功能? JVM不是魔术,它只是一个像其他一切一样的程序。在某些级别,您需要拥有本机代码才能让CPU执行它,因此在本机代码中可以使用垃圾收集这些功能

答案 4 :(得分:0)

对于您目前所处的位置,最好将(GHC)Haskell视为“托管”,但the platform GHC compiles to不是其他任何目标。当然,它more than that,但这足以说明Haskell的更多经验。