type family Equal (k :: Type) (a :: k) (b :: k) where
Equal k ((f :: j -> k) (a :: j)) ((g :: j -> k) (b :: j)) =
Equal (j -> k) f g && Equal j a b
Equal k a a = 'True
Equal k a b = 'False
This == behaves in a much more uniform way than the current one. I see two potential causes for complaint:
1. For types of kind *, the new version will sometimes fail to reduce when the old one succeeded (and vice versa). For example, GHC currently accepts
eqeq :: forall (a :: *). proxy a -> (a == a) :~: 'True
eqeq _ = Refl
while the proposed version does not.
2. Some users may want non-structural equality on their types for some reason. The only example in base is
type instance (a :: ()) == (b :: ()) = 'True
which consists two types of kind () the same even if they're stuck types. But perhaps someone wants to implement a non-trivial type-level data structure with a special notion of equality.
I don't think (1) is really worth worrying too much about. For (2), if users want to have control, we could at least use a mechanism similar to the above to make the obvious instances easier to write.