Предположим, у меня есть простой перечислимый тип с 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 всегда создавать симпатичные экземпляры (даже если код, который на самом деле выполняется, тайно использует уродливые под капотом). В идеале мне не пришлось бы изменять исходный код (в противном случае я бы, вероятно, просто укусил бы пулю и сам написал бы красивые экземпляры).
Возможно ли это в настоящее время?