Type families and typeclass instance constraints?

I have a Haskell typeclass that makes use of type families:

class Goodness a where
  type Rating a :: Type

  is_good :: Rating a -> a -> bool

I can implement this typeclass for concrete types:

instance Goodness Int where
  type Rating Int = Int

  is_good :: Int -> Int -> bool
  is_good r x = x >= r

I’d like to be able to implement the typeclass for any homogeneous 2-tuple of types that implement Goodness:

instance (Goodness a) => Goodness (a, a) where
  type Rating (a, a) = a

  is_good :: a -> (a, a) -> bool
  is_good r t = is_good r (fst t) && is_good r (snd t)

I’m not sure this approach is even advisable and the compiler is rightly complaining about matching the a in the instance constraint versus the Rating a type. I think I’m missing something about type families here–can anyone advise?

TIA,

Stu

1 Like

Your problem is that the is_good in is_good r (fst t) has as type

is_good :: Rating a -> a -> Bool

and you are using it as

is_good :: Rating (a,a) -> a -> Bool

You either need to use it differently or specify in the instance head that Rating a is equal to Rating (a, a).

This works:

instance (Goodness a, Rating a ~ Rating (a, a)) => Goodness (a, a) where
  type Rating (a, a) = a

  is_good :: a -> (a, a) -> Bool
  is_good r (t1,t2) = is_good r t1 && is_good r t2
1 Like

Thank you for that clear explanation, much appreciated.

1 Like