假设我有一个简单的类型类(type class),其实例会给我某种类型(type)的值:
trait GiveMeJustA[X] { def apply(): X }
我有一些实例:
case class Foo(s: String)
case class Bar(i: Int)
implicit object GiveMeJustAFoo extends GiveMeJustA[Foo] {
def apply() = Foo("foo")
}
implicit object GiveMeJustABar extends GiveMeJustA[Bar] {
def apply() = Bar(13)
}
现在我有一个类似的(但不相关)类型类,它做相同的事情,但其类型参数是协变的:
trait GiveMeA[+X] { def apply(): X }
在其伴生对象中,我们告诉编译器如何从非协变类型类的实例创建实例:
object GiveMeA {
implicit def fromGiveMeJustA[X](implicit giveMe: GiveMeJustA[X]): GiveMeA[X] =
new GiveMeA[X] { def apply() = giveMe() }
}
现在我期望implicitly[GiveMeA[Foo]]
可以编译通过,因为我们只有一个方法可以获得GiveMeA[Foo]
,但它并没有(至少在2.10.4或2.11.2上不行):
scala> implicitly[GiveMeA[Foo]]
<console>:16: this.GiveMeA.fromGiveMeJustA is not a valid implicit value for GiveMeA[Foo] because:
hasMatchingSymbol reported error: ambiguous implicit values:
both object GiveMeJustAFoo of type GiveMeJustAFoo.type
and object GiveMeJustABar of type GiveMeJustABar.type
match expected type GiveMeJustA[X]
implicitly[GiveMeA[Foo]]
^
<console>:16: error: could not find implicit value for parameter e: GiveMeA[Foo]
implicitly[GiveMeA[Foo]]
^
如果我们删除无关的 GiveMeJustA
实例,它就可以工作:
scala> implicit def GiveMeJustABar: List[Long] = ???
GiveMeJustABar: List[Long]
scala> implicitly[GiveMeA[Foo]]
res1: GiveMeA[Foo] = GiveMeA$$anon$1@2a4f2dcc
尽管我们无法将GiveMeA.fromGiveMeJustA
应用于此实例以获取GiveMeA[Foo]
(或任何GiveMeA[Foo]
的子类型),但仍然存在这种情况。
我认为这看起来像是一个bug,但也有可能我漏掉了什么。这有任何意义吗?是否有合理的解决方法?