通过父类型获取类型 class 实例

Getting type class instance through a parent type

我需要为一堆案例 class 提供类型 class 实例,这些实例都是从单个特征派生的,但据我了解,Scala 编译器需要一个特定实例 class 并且不会上升到继承层次结构。所以这段代码:

trait Base

sealed trait Child extends Base

case class Concrete() extends Child

trait Printable[A] {
  def print(value: A): String
}

object WtfTrait {
  def print[A](x: A)(implicit ev: Printable[A]) = {
    println(ev.print(x))
  }

  implicit val printableBase = new Printable[Base] {
    override def print(value: Base): String = value.toString
  }

  val x = Concrete()
  print(x)
}

没有编译错误读取 could not find implicit value for parameter ev: Printable[Impl]。有没有办法为基本特征定义单一类型 class 实例,并避免重复使用 Shapeless 或其他东西。

我猜你是说 Printable[Concrete](也就是说 Show 类型类实例)。

需要更新为 printableBase 定义如下:

trait Base

sealed trait Child extends Base

case class Concrete() extends Child

trait Printable[A] {
  def print(value: A): String
}

object WtfTrait {
  def print[A](x: A)(implicit ev: Printable[A]) = {
    println(ev.print(x))
  }

  // HERE
  implicit def printableBase[T <: Base] = new Printable[T] {
    override def print(value: T): String = value.toString
  }

  val x = Concrete()
  print(x)
}

Printable 可以通过添加 - 符号来实现逆变:

trait Printable[-A]

这使得 Printable[X] 成为 Printable[Y] 的子类型,如果 YX 的子类型。特别是,Printable[Base]Printable[Concrete] 的子类型,可以在编译器查找该类型的隐式时使用。