1

我有以下代码定义类型类。

trait Foo[T] {
  def toFoo(x: T): String
}

trait Foos {
  def toFoo[T](f: T => String): Foo[T] = new Foo[T] {
    def toFoo(x: T): String = f(x)
  }
}

object Foo extends Foos {
  def toFoo[A: Foo](a: A) = implicitly[Foo[A]].toFoo(a)
  implicit def AToFoo: Foo[A] = toFoo { c =>
    "A"
   }
  implicit def BToFoo[T]: Foo[B] = toFoo { c  => 
    "B"
  }

  implicit def ListToFoo[T: Foo]: Foo[List[T]] = toFoo { c =>
    c.map(toFoo(_)).
  }
}

class A
class B extends A

现在,如果我有的话,我会toFoo(List(new A, new B)得到List("A", "A")而不是List("A", "B"). 如何确保使用该BtoFoo方法而不是AToFoo用于具有 type 的类B

4

1 回答 1

2

隐式解析是一种纯粹的编译时机制。这里区分子类型的简单方法是在隐式内部进行匹配。完全删除BToFoo,而是让A版本处理这两种情况

implicit val AIsFoo : Foo[A] = toFoo { 
  case b: B => "B"
  case a: A => "A"
}

当然,也可以将部分层次结构委托给方法。您可以委托给 in 中的方法A,overidde in B,并且仍然让类型类为 List 工作,您无法在其中添加方法。

您也可以考虑声明Foo逆变。

于 2012-03-20T11:28:36.760 回答