Search code examples
scalacovarianceimplicit

Implicit processor for all subtypes


I have some types

trait Processor[+A] {
  def handle[B >: A](a: B): Unit
}

trait TypeA

case class A1() extends TypeA

and a method

def process[A](a: A)(implicit processor: Processor[A])

can I have something like

implicit val processor = new Processor[TypeA] {
  def handle[B >: TypeA](a: B): Unit = {
    println(a)
  }
}

so that it will handle all subtype of TypeA? e.g.

process(A1())

but in my case it just gives

scala> process(A1())
<console>:29: error: could not find implicit value for parameter processor: Processor[A1]
              process(A1())

Solution

  • What covariance does is precisely the opposite: it means that a Processor[A1] is a Processor[TypeA], so a processor for a type can handle all its supertypes.

    So if you need a Processor to handle all subtypes of a type instead, you need contravariance. And your trait looks exactly like it should in fact be contravariant (but this may be due to simplification for the question):

    trait Processor[-A] {
      def handle(a: A): Unit
    }
    
    implicit val processor: Processor[TypeA] = new Processor[TypeA] {
      def handle(a: TypeA): Unit = {
        println(a)
      }
    }
    

    Then process(A1()) works.