scala - Creating instances of a covariant type class from instances of a non-covariant one -
suppose i've got simple type class instances give me value of type:
trait givemejusta[x] { def apply(): x } and i've got 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 have similar (but unrelated) type class same thing covariant in type parameter:
trait givemea[+x] { def apply(): x } in companion object tell compiler how create instances 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]] compile fine, since there's 1 way givemea[foo] given pieces have here. doesn't (at least not on either 2.10.4 or 2.11.2):
scala> implicitly[givemea[foo]] <console>:16: this.givemea.fromgivemejusta not valid implicit value givemea[foo] because: hasmatchingsymbol reported error: ambiguous implicit values: both object givemejustafoo of type givemejustafoo.type , object givemejustabar of type givemejustabar.type match expected type givemejusta[x] implicitly[givemea[foo]] ^ <console>:16: error: not find implicit value parameter e: givemea[foo] implicitly[givemea[foo]] ^ if rid of our irrelevant givemejusta instance, works:
scala> implicit def givemejustabar: list[long] = ??? givemejustabar: list[long] scala> implicitly[givemea[foo]] res1: givemea[foo] = givemea$$anon$1@2a4f2dcc this in spite of fact there's no way can apply givemea.fromgivemejusta instance givemea[foo] (or subtype of givemea[foo]).
this looks bug me, it's possible i'm missing something. make sense? there reasonable workaround?
i not understand why working, following code resolves implicit in current case (at least on scala v-2.10.1). however, still not explains why example not working in first place:
we change implicit givemea[x] instance search implicit givemejusta instances type parameter bounded upwards x, searches givemejusta[_ <: x]
object givemea { implicit def fromgivemejusta[x](implicit giveme: givemejusta[_ <: x]) : givemea[x] = new givemea[x] { def apply() = giveme() } } we can print out expected output
val = implicitly[givemea[foo]] println(a()) // prints "foo(foo)" however, introduce new subclass
case class foochild(s: string) extends foo(s) and respective givemejusta typeclass instance
implicit object givemejustafoochild extends givemejusta[foochild] { def apply() = foochild("foochild") } the compiler complains (as expected)
error: not find implicit value parameter e: givemea[foo] val = implicitly[givemea[foo]]
Comments
Post a Comment