Haskell是一种非常好的语言。我喜欢它。但作为一名C ++程序员并且有一些关于计算机体系结构的基本知识,我真的想知道有关Haskell的实现细节。
我的意思是,例如,map
功能。我知道语法,结果。但是,我想知道这个功能在RAM中是如何工作的。因为C族语言非常清楚语法和计算机行为之间的映射。
那么有没有人对功能程序语法背后的计算机行为有所了解?或者关于这个的任何书籍都像“在C ++对象模型中”?
答案 0 :(得分:5)
首先,警告:Haskell的一个基本属性是编译器高度可能在编译期间对代码执行非常激进的转换。因此,实际执行的代码可能与您编写的代码完全不同。
这一点需要注意,对于第一个近似值,您可以期望每个变量和每个数据字段都是指向堆对象的指针。其中一些堆对象表示数据(整数,bool,字符,列表节点等),其中一些表示由于懒惰而尚未执行的Haskell代码。如果编写一个长而复杂的表达式,则每个子表达式都成为一个堆对象,顶层表达式指向较低的表达式。因此,程序的整个表达式图形成为堆上的对象图。
(Graph / = tree。树中没有“循环”.Haskell允许递归,因此Haskell表达式不一定是表达式 trees 。)
Big Haskell表达式成为一大堆堆对象。复杂的嵌套模式匹配以最佳顺序被移植到一系列单层模式中。该语言的所有其他语法糖都被剥离,直到只剩下6个原语:
如果你想知道实际的位和字节是如何工作的,那就是编译器。如果你的意思是GHC,它的工作方式大致如下:
每个堆对象都是代码或数据。
如果是数据,它包含一个值构造函数ID号和每个构造函数字段的一个指针。
如果它是代码(即一些尚未执行的子表达式),它包含一个指向函数机器代码块的指针,以及一个指向每个函数参数的指针(没有currying)。
当您尝试在堆对象上执行条件分支,I / O操作或seq
时,运行时会跳转到堆对象指向的某些代码。
如果对象代表数据,它将指向一些即时返回的代码。
如果对象代表代码,它将指向实际实现该函数的代码。此代码计算函数的答案,并使用表示答案的数据对象覆盖原始堆对象。
无论哪种方式,当控制权返回给调用者时,堆对象肯定是一个数据对象,它现在可以检查构造函数ID或其他任何想做的事情。
答案 1 :(得分:4)
实现惰性函数语言的基本思想称为图形缩减。
“函数式编程语言的实现”是一本关于这一主题的详细的旧书:http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/
更类似教程的介绍:http://research.microsoft.com/en-us/um/people/simonpj/papers/pj-lester-book/
有关如何实施GHC的更多信息,您可以查看“Spineless Tagless G-Machine”(STGM)论文,例如:http://www.dcc.fc.up.pt/~pbv/aulas/linguagens/peytonjones92implementing.pdf
答案 2 :(得分:4)
有一本非常好的书介绍了使用惰性图缩减实现函数语言的细节:
Implementing functional languages: a tutorial。 Simon Peyton Jones和David Lester,1992年。
本书提供了一种实用的方法来理解使用惰性图缩减的非严格函数语言的实现。本书旨在成为实用实验室材料的来源,通过帮助读者开发,修改和试验一些非平凡的编译器,帮助使功能语言实现“活跃起来”。
本书的不寻常之处在于它既可以执行也可以阅读。我们不仅仅提供每种实现技术的抽象描述,而是为每种主要方法的完整工作原型提供代码,然后对其进行一系列改进。所有代码都以机器可读的形式提供。
请注意,本书与The Implementation of Functional Programming Languages不同, Simon Peyton Jones,1987年(也很有趣)。