scalatypeclasssuperclassimplicittype-members

Resolve implicit parameter from super type


Is it possible to resolve an implicit parameter for a type B if an implicit is defined for its super type A?

Here is an example :

I have an Enumerable typeclass :

trait Enumerable[A] {

  def name(a: A): String

  def list: List[A] 

  //... other methods
}

object Enumeration {
  def name[A, T >: A](a: A)(implicit ev: Enumerable[T]) = ev.name(a)

  def list[T](implicit ev: Enumerable[T]) = ev.list

  // ...
}

Then I define an instance of enumerable :

sealed trait Season

case object Winter extends Season
case object Spring extends Season
case object Summer extends Season
case object Fall extends Season

implicit val seasonEnumerable = new Enumerable[Season] {
  override def list: List[Season] = List(Winter, Spring, Summer, Fall)
}

// working : 
Enumeration.name(Winter: Season) shouldBe "winter"

// faling : 
Enumeration.name(Winter) shouldBe "winter"

Enumeration.name(Winter) is failing if I don't tell scalac that Winter is a Season. I've specified that the implicit parameter in the 'name' method signature is a supertype of A, but it's not sufficient...

Is there a better way to do this?


Solution

  • Eduardo's answer explains why the version with [A, T >: A] doesn't work. But there is a simpler solution to the problem than he gives: instead of introducing T infer as a type parameter, introduce it by an existential type:

    def name[A](a: A)(implicit ev: Enumerable[T >: A] forSome { type T }) = ev.name(a)
    

    Or, using a shorthand,

    def name[A](a: A)(implicit ev: Enumerable[_ >: A]) = ev.name(a)
    

    Then the compiler only has to decide what T is when looking for ev.