Haskell中的WHNF减少是否发生在编译时?

时间:2017-11-25 07:53:29

标签: haskell functional-programming

AFAIU Haskell compiler生成的目标文件应该是机器代码。那么该对象文件是否具有原始AST的表示并在运行时减少它,或者在编译时进行此减少,并且只将最终WHNF值转换为相应的机器代码。

我理解后者的编译时间是程序本身时间复杂度的函数,我认为不太可能。

有人可以清楚地解释在运行时会发生什么以及在Haskell (GHC)的情况下编译时会发生什么?

1 个答案:

答案 0 :(得分:6)

编译器可以在运行时执行其所有减少的工作。也就是说,生成的可执行文件可能有一个(大)数据部分,其中整个程序AST被编码,以及一个(小)文本/代码部分,其中包含一个在AST上运行的通用WHNF减速器。

请注意,上述方法适用于任何语言。例如。 Python编译器还可以生成包含AST数据和通用reducer的可执行文件。 reducer将遵循语言的所谓小步语义,这是计算机科学中一个众所周知的概念(更具体地说,在编程语言理论中)。

然而,这种方法的表现会很差。

编程语言的研究人员致力于寻找更好的方法,从而定义抽象机器。本质上,抽象机是用于在较低级别设置中运行高级程序的算法。通常,它利用一些数据结构(例如堆栈)来使该过程更有效。对于像Haskell这样的函数式语言,众所周知的抽象机器包括:

问题本身远非微不足道。已经有,并且我认为仍有研究使WHNF降低效率更高。

在GHC编译之后,每个Haskell定义都成为一系列汇编指令,它们操纵STG机器的状态。周围没有AST,只有操作数据/闭包等的代码。

可以说,使用这些先进技术来提高性能以及大量优化是非常重要的。然而,一个消极的后果是,很难理解最终代码的性能,因为需要考虑抽象机器的工作原理(这是非常重要的)和优化(非常复杂)如今)。在较小程度上,这也是大量优化C或C ++编译器的情况,在这种情况下,更难以了解何时触发优化。

最终,一位经验丰富的程序员(在Haskell,C,C ++或其他任何方面)将会理解其编译器的基本优化,以及正在使用的抽象机器的基本机制。但是,我认为这不容易掌握。

在这个问题中,提到WHNF减少可以在编译时执行。这只是部分正确,因为直到运行时才能知道源自IO动作的变量的值,因此减少只能在涉及这些值的运行时发生。此外,执行减少也会使性能变差! E.g。

let x = complex computation in x + x
-- vs
complex computation + complex computation

后者是减少前者的结果,但它重复了工作!实际上,大多数抽象机器都使用惰性约简方法,在这种情况下只能计算x一次。