Overlapping instances for `Compose` with `Contravariant` and `Functor`

Viewed 69

While solving the last exercise of this course, I realized that not only we can have

instance (Functor f, Contravariant g) => Contravariant (Compose f g) where
-- Implement the (>$<) function for a Contravariant instance for Compose
  (>$<) :: (b -> a) -> Compose f g a -> Compose f g b
  fun >$< Compose fga = Compose ((fun >$<) <$> fga)

but also

instance (Contravariant f, Functor g) => Contravariant (Compose f g) where
-- Implement the (>$<) function for a Contravariant instance for Compose
  (>$<) :: (b -> a) -> Compose f g a -> Compose f g b
  fun >$< Compose fga = Compose ((fun <$>) >$< fga)

The problem is that I cannot get the module to compile when I put both definitions. The error I get is

    Duplicate instance declarations:
      instance (Functor f, Contravariant g) =>
               Contravariant (Compose f g)
        -- Defined at /.../fp-course/src/Course/Compose.hs:62:10
      instance (Contravariant f, Functor g) =>
               Contravariant (Compose f g)
        -- Defined at /.../fp-course/src/Course/Compose.hs:71:10
   |
62 | instance (Functor f, Contravariant g) =>
   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...

and I couldn't manage to get rid of it by adding the deprecated extension {-# LANGUAGE OverlappingInstances #-} or the {-# OVERLAPPABLE #-}/{-# OVERLAPPING #-}/{-# OVERLAPS #-} pragmas as explained here.

Is there a way to have both definitions in the module?


Edit: sorry I forgot to mention that the course redefines custom type classes Functor, Contravariant, etc... (>$<) corresponds to contramap.

0 Answers
Related