Haskell编译器魔术:什么需要编译器的特殊处理?

时间:2016-03-02 00:56:16

标签: haskell ghc

当试图学习Haskell时,出现的困难之一就是当某些东西需要来自编译器的特殊魔法时。我们想到的一个例子是seq函数,它无法定义,即您不能使seq2函数的行为与内置seq完全相同。因此,在向某人讲授seq时,您需要提及seq是特殊的,因为它是编译器的特殊符号。

另一个例子是do - 符号,它仅适用于Monad类的实例。

有时,它并不总是显而易见的。例如,延续。编译器是否知道Control.Monad.Cont或者您是否可以自己发明的旧Haskell?在这种情况下,我认为即使延续是一种非常奇怪的野兽,编译器也不需要特殊的东西。

语言扩展被搁置,其他编译器魔术Haskell学习者应该注意什么?

2 个答案:

答案 0 :(得分:5)

几乎所有无法在userland中实现的ghc基元都在ghc-prim包中。 (它甚至有一个名为GHC.Magic的模块!)

所以浏览它会很有意义。

请注意,除非您确切知道自己在做什么,否则在用户区代码中使用此模块。它中的大多数可用内容都是base中的下游模块导出的,有时是修改后的形式。那些下游位置和API被认为更稳定,而ghc-prim不保证它将如何在版本之间起作用。

GHC特定的东西会在GHC.Exts中重新导出,但很多其他东西会进入Prelude(例如基本数据类型,以及seq)或并发库等。< / p>

答案 1 :(得分:1)

多态seq绝对是神奇的。您可以为任何特定的类型实现seq,但只有编译器可以为所有可能类型实现一个函数[并避免优化即使它看起来没有了,也离开了。

显然整个IO monad是非常神奇的,就像并发和并行(parforkIOMVar),可变存储,异常抛出和捕获,查询垃圾收集器和运行时统计信息等。

IO monad可以被认为是ST monad的特例,这也是魔法。 (它允许真正可变的存储,这需要低级别的东西。)

另一方面,State monad是完全普通的用户级代码,任何人都可以编写。 Cont monad也是如此。各种异常/错误monad也是如此。

与语法(do-blocks,list comprehensions)有关的任何内容都是硬连接到语言定义中的。 (但请注意,其中一些响应LANGUAGE RebindableSyntax,它允许您更改它绑定的功能。)还有deriving个东西;编译器“了解”一些特殊类以及如何为它们自动生成实例。派生newtype适用于任何类。 (它只是将一个实例从一种类型复制到另一种类型的相同副本。)

阵列是硬接线的。就像其他编程语言一样。

所有外部功能界面显然都是硬接线。

STM 可以在用户代码中实现(我已经完成了),但它目前是硬连线的。 (我想这会带来显着的性能优势。我还没有尝试过实际测量它。)但是,从概念上讲,这只是一种优化; 可以使用现有的低级并发原语来实现它。