Here you need a functional dependency: use
class Eq b => HasPK ab | a -> b where getPK :: a -> b
and enable all GHC extension points.
The problem is being able to have multiple PKs for the same type as in
instance HasPK MyType Int where ... instance HasPK MyType String where ...
Since the aforementioned double instance can be added later, code like (==) `on` getPK potentially ambiguous. Indeed, when added instances are added, it does not indicate whether to use Int PK or String .
However, an instance of type
instance (HasPK ab) => Eq a where ...
can cause problems because it overlaps with any other instance of Eq . Be careful. I will write instead
equalPK :: HasPK ab => a -> a -> Bool equalPK = (==) `on` getPK
and then provide explicit instances to all relevant types as follows:
instance Eq MyType1 where (==) = equalPK instance Eq MyType2 where (==) = equalPK ...
As another alternative, you can use a type family like
class HasPK a where type PK a getPK :: a -> PK a equalPK :: Eq (PK a) => a -> a -> Bool equalPK = (==) `on` getPK instance Eq MyType1 where (==) = equalPK ...
chi
source share