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

abh*_*hek 4 haskell functional-programming

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

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

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

chi*_*chi 6

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

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

但是,这种方法的表现会很差.

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

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

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

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

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

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

let x = complex computation in x + x
-- vs
complex computation + complex computation
Run Code Online (Sandbox Code Playgroud)

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