0

I have the following trait...

import cats._
import cats.implicits._

trait Preference[-A] {
  self =>

  def compare(a1: A, a2: A): Int

  final def ordering[A1 <: A]: Ordering[A1] = {
    new Ordering[A1] {
      def compare(a1: A1, a2: A1): Int = {
        self.compare(a1, a2)
      }
    }
  }

}


object Preference {

  implicit val contravariant: Contravariant[Preference] = {
    new Contravariant[Preference] {
      def contramap[A, B](fa: Preference[A])(f: B => A): Preference[B] = {
        new Preference[B] {
          def compare(b1: B, b2: B): Int = {
            fa.compare(f(b1), f(b2))
          }
        }
      }
    }
  }
}

I would like to define Apply, Applicative, possibly even Monad instances for this trait but all of these type classes are extensions of Functor. Do versions of these type classes exist in Cats for contravariant functors?

davidrpugh
  • 4,363
  • 5
  • 32
  • 46
  • 1
    I find that this infographic can often help with this kind of thing: https://github.com/tpolecat/cats-infographic – Joe K Jul 12 '18 at 17:46

1 Answers1

2

The contravariant equivalent of Applicative in Haskell is Divisible, and cats.ContravariantMonoidal allows to define both of its methods (divide is contramap2, conquer is trivial). I am not immediately certain, though, if any Divisible has to be Monoidal in cats' sense.

For Monad, Kmett says

There is no contravariant Monad-like. You need C -> C, not C -> C^op. The twist denies you the ability to build nice structure.

Also Are there contravariant monads?.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487