Suppose I've got a simple type class whose instances will give me a value of some type:
trait GiveMeJustA[X] { def apply(): X }
And I've got some instances:
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)
}
Now I have a similar (but unrelated) type class that does the same thing but is covariant in its type parameter:
trait GiveMeA[+X] { def apply(): X }
In its companion object we tell the compiler how to create instances from instances of our non-covariant type class:
object GiveMeA {
implicit def fromGiveMeJustA[X](implicit giveMe: GiveMeJustA[X]): GiveMeA[X] =
new GiveMeA[X] { def apply() = giveMe() }
}
Now I'd expect implicitly[GiveMeA[Foo]]
to compile just fine, since there's only one way to get a GiveMeA[Foo]
given the pieces we have here. But it doesn't (at least not on either 2.10.4 or 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]]
^
If we get rid of our irrelevant GiveMeJustA
instance, it works:
scala> implicit def GiveMeJustABar: List[Long] = ???
GiveMeJustABar: List[Long]
scala> implicitly[GiveMeA[Foo]]
res1: GiveMeA[Foo] = GiveMeA$$anon$1@2a4f2dcc
This is in spite of the fact that there's no way we can apply GiveMeA.fromGiveMeJustA
to this instance to get a GiveMeA[Foo]
(or any subtype of GiveMeA[Foo]
).
This looks like a bug to me, but it's possible that I'm missing something. Does this make any sense? Is there a reasonable workaround?
Generic
whereGiveMeJustA
is being used. And in that case the solution doesn't seem to work, I'm guessing because of the macros. – Howitzer