davidrpugh
davidrpugh

Reputation: 4553

Apply, Applicative, Monad, etc for contravariant functors in cats?

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?

Upvotes: 0

Views: 113

Answers (1)

Alexey Romanov
Alexey Romanov

Reputation: 170713

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?.

Upvotes: 2

Related Questions