Suppose I have a simple enumerated type with 10 elements:
data Test = A | B | C | D | E | F | G | H | I | J
deriving Eq
GHC derives the Eq
instance as you'd expect:
==================== 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
However, once you add an 11th constructor K
, GHC changes the way the instance is derived (ostensibly for efficiency reasons):
==================== 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
The issue
I'm using a tool that consumes Haskell source code and it can easily handle the former pretty-looking instances but not the latter ugly ones. 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). Ideally, I would not have to modify the source code (otherwise, I'd probably just bite the bullet and hand-write the pretty instances myself).
Is this currently possible?
Ord
instances, since those have N^2 cases for N constructors. I'm not really sure why this is used forEq
, but it might be to let the optimizer be a bit more clever whenEq
andOrd
code are used together. – dfeuer