【发布时间】:2016-03-02 00:56:16
【问题描述】:
在尝试学习 Haskell 时,出现的困难之一是当某些事情需要编译器提供特殊魔法时的能力。想到的一个例子是无法定义的seq 函数,即您不能使seq2 函数的行为与内置seq 完全相同。因此,在向某人介绍seq 时,您需要提及seq 是特殊的,因为它是编译器的特殊符号。
另一个例子是 do-notation,它只适用于 Monad 类的实例。
有时,这并不总是显而易见的。例如,延续。编译器是否知道 Control.Monad.Cont 或者您可以自己发明的普通的旧 Haskell?在这种情况下,我认为编译器不需要什么特别的东西,即使延续是一种非常奇怪的野兽。
抛开语言扩展,Haskell 学习者应该注意哪些其他编译器魔法?
【问题讨论】:
-
显而易见:
IO任何合理的“魔法”定义都属于“魔法”:reddit.com/r/haskell/comments/450baq/…。还有STmonad,这可能更神奇。 -
STM 怎么样?和流融合?
-
我不确定我是否会称之为流融合魔法。您可以创建自己的重写规则,因此这更像是语言的工具而不是魔法(至少在 GHC 扩展的 Haskell 中)。此外,如果事情是间接的、间接的魔法,只是因为他们使用了其他魔法,那么看起来几乎所有东西都是魔法,因为你最终最终会到达
IO。当然,STM可能更偏向于魔法方面,因为它可能在某些时候在内部直接使用像State# RealWorld这样的东西。 -
GHC 开发人员通常称之为“魔法”的东西是那些从编译器得到特殊处理的东西。
Coercible(定义为data,并神奇地更改为k -> k -> Constraint)和lazy(“神奇地”使GHC认为函数是惰性的)就是很好的例子。 -
请参阅here 了解 GHC 源代码中定义原始标识符(即函数)的部分。也许唯一令人惊讶的原始事物是
($) :: (a -> b) -> (a -> b)。