有没有理由首先运行类型检查器?如果它运行在较小的语法上,那么类型检查器似乎会变得非常简单,特别是因为在当前系统中,每个语法扩展都需要触及类型检查器。这个问题特别适用于箭头语法,其中as described in comments here被称为伪造的类型检查。
我想这样做的一个原因是不会发出提及生成代码的错误,但是在deriving
子句未能进行类型检查的情况下已经涵盖了这种情况。 GHC知道代码是生成的。
答案 0 :(得分:28)
在本书第2卷"开源应用程序架构"中找到的GHC article中有一个关于此问题的部分:
类型检查源语言
一个有趣的设计决定是 是否应在脱毒前后进行型式检查。该 权衡是这些:
desugaring之前的类型检查意味着类型检查器必须处理 直接使用Haskell非常大的语法,因此类型检查器具有 很多情况需要考虑。如果我们贬低(一种无类型的变体) 核心第一,人们可能希望类型检查器会变得更多 小。
另一方面,desugaring后的类型检查会 强加一项重要的新义务:这种贬义不会影响 哪些程序是类型正确的。毕竟,desugaring意味着一个 故意丢失信息。可能就是95%的情况 案件没有问题,但这里的任何问题都会迫使一些问题 在Core的设计中妥协以保留一些额外的信息。
最重要的是,键入检查一个荒谬的程序就可以了 报告与原始程序文本相关的错误要困难得多, 而不是它(有时复杂的)desugared版本。
大多数编译器在desugaring之后键入check,但对于GHC我们做出了相反的选择: 我们键入检查完整的原始Haskell语法,然后desugar 结果。听起来好像添加一个新的句法结构可能是 复杂,但(继法国学校之后)我们已经构建了 类型推理引擎的方式使其变得简单。类型推断是 分为两部分:
约束生成:遍历源语法树,生成一个 类型约束的集合。此步骤处理完整语法 Haskell,但它是非常简单的代码,并且很容易添加 新病例。
约束求解:解决聚集的约束。这是 类型推理引擎的微妙之处在哪里,但确实如此 独立于源语言语法,并且对于a来说是相同的 更小或更大的语言。
总的来说, type-check-before-desugar设计选择已经证明是一个很大的选择 赢得。是的,它为类型检查器添加了代码行,但它们是 简单的线条。它避免了为同一数据提供两个冲突的角色 类型,并使类型推理引擎不那么复杂,而且更容易 修改。此外,GHC的类型错误消息非常好。