假设我有一个包含10个元素的简单枚举类型:
data Test = A | B | C | D | E | F | G | H | I | J
deriving Eq
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
但是,一旦添加了第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
Run Code Online (Sandbox Code Playgroud)
问题
我正在使用一个消耗Haskell源代码的工具,它可以轻松处理以前漂亮的实例,但不能处理后者的丑陋实例.我希望有一个标志,迫使GHC始终生成漂亮的实例(即使实际运行的代码秘密使用丑陋的实例).理想情况下,我不必修改源代码(否则,我可能只是咬紧牙关并自己手写漂亮的实例).
这目前可能吗?
如果你对此非常关心,你可以自己写一些TH来生成"更漂亮"的Eq实例.您可以从Ryan的deriving-compat软件包中获取灵感,该软件包具有deriveEq :: Name -> Q [Dec](您不能直接使用它,因为Ryan,一如既往,确保为具有10个以上构造函数的数据类型提供完全相同的特殊逻辑).
我希望有一个标志,迫使GHC始终生成漂亮的实例(即使实际运行的代码秘密使用丑陋的实例).
不.看起来10是一个常量硬编码,代码Eq是如何生成的(源代码).
| 归档时间: |
|
| 查看次数: |
81 次 |
| 最近记录: |