【问题标题】:Is there any way to control how GHC derives `Eq` instances?有什么方法可以控制 GHC 如何派生“Eq”实例?
【发布时间】:2018-10-30 20:16:43
【问题描述】:

假设我有一个包含 10 个元素的简单枚举类型:

data Test = A | B  | C | D | E | F | G | H | I | J
  deriving Eq

GHC 派生出您所期望的 Eq 实例:

==================== Derived instances ====================
Derived class instances:
  instance GHC.Classes.Eq Test.Test where
    (GHC.Classes.==) (Test.A) (Test.A) = GHC.Types.True
    (GHC.Classes.==) (Test.B) (Test.B) = GHC.Types.True
    (GHC.Classes.==) (Test.C) (Test.C) = GHC.Types.True
    (GHC.Classes.==) (Test.D) (Test.D) = GHC.Types.True
    (GHC.Classes.==) (Test.E) (Test.E) = GHC.Types.True
    (GHC.Classes.==) (Test.F) (Test.F) = GHC.Types.True
    (GHC.Classes.==) (Test.G) (Test.G) = GHC.Types.True
    (GHC.Classes.==) (Test.H) (Test.H) = GHC.Types.True
    (GHC.Classes.==) (Test.I) (Test.I) = GHC.Types.True
    (GHC.Classes.==) (Test.J) (Test.J) = GHC.Types.True
    (GHC.Classes.==) _ _ = GHC.Types.False

但是,一旦添加了第 11 个构造函数 K,GHC 就会改变实例的派生方式(表面上是出于效率原因):

==================== Derived instances ====================
Derived class instances:
  instance GHC.Classes.Eq Test.Test where
    (GHC.Classes.==) a_a1uD b_a1uE
      = case (Test.$con2tag_7MvV0ZqFtYZ8X4oGLC1npJ a_a1uD) of {
          a#_a1uF
            -> case (Test.$con2tag_7MvV0ZqFtYZ8X4oGLC1npJ b_a1uE) of {
                 b#_a1uG -> (GHC.Prim.tagToEnum# (a#_a1uF GHC.Prim.==# b#_a1uG)) } }

  Test.$con2tag_7MvV0ZqFtYZ8X4oGLC1npJ :: Test.Test -> GHC.Prim.Int#
  Test.$con2tag_7MvV0ZqFtYZ8X4oGLC1npJ a_a1uC
    = GHC.Base.getTag a_a1uC

问题

我正在使用一个使用 Haskell 源代码的工具,它可以轻松处理前者漂亮的实例,但不能处理后者丑陋的实例。我希望有一个标志可以强制 GHC 始终生成漂亮的实例(即使实际运行的代码在后台偷偷使用丑陋的实例)。理想情况下,我不必修改源代码(否则,我可能只好硬着头皮自己手写漂亮的实例)。

目前可以吗?

【问题讨论】:

  • 这将提出一个非常好的 GHC 功能请求。没有内在的理由不让编译器标志更改阈值。该策略的主要目标是处理 Ord 实例,因为这些实例对于 N 个构造函数有 N^2 个案例。我不太确定为什么要使用 Eq,但可能是在 EqOrd 代码一起使用时让优化器更聪明。

标签: haskell ghc


【解决方案1】:

如果你足够关心这个,你可以给自己写一些 TH 来生成“更漂亮的”Eq 实例。您可以从 Ryan 的 deriving-compat 包中获得灵感,该包具有 deriveEq :: Name -> Q [Dec](您不能直接使用它,因为 Ryan 一如既往地彻底,确保为具有 10 多个构造函数的数据类型移植完全相同的特殊逻辑)。

我希望有一个标志可以强制 GHC 始终生成漂亮的实例(即使实际运行的代码在后台偷偷使用丑陋的实例)。

没有。看起来 10 是如何生成 Eq 代码的常量硬编码 (source)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-08
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 2021-11-13
    • 2012-06-13
    相关资源
    最近更新 更多