有没有办法控制 GHC 如何派生“Eq”实例?

Is there any way to control how GHC derives `Eq` instances?

假设我有一个包含 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 始终生成漂亮的实例(即使实际上 运行 的代码在幕后秘密使用丑陋的实例)。理想情况下,我不必修改源代码(否则,我可能会硬着头皮自己手写漂亮的实例)。

目前可以吗?

如果您对此足够关心,您可以自己编写一些 TH 来生成 "prettier" Eq 个实例。你可以从 Ryan 的 deriving-compat 包中获得灵感,它有 deriveEq :: Name -> Q [Dec](你不能直接使用它,因为 Ryan 一如既往地彻底,确保为超过10 个构造函数)。

What I'm hoping is that there is a flag that forces GHC to always produce the pretty instances (even if the code that is actually run is secretly using the ugly ones under the hood).

没有。看起来 10 是硬编码到 Eq 代码生成方式中的常量 (source)。