I am trying to express a constraint like:
in a method def run[A, B](...), B must be equal to A#SomeInner
Here is my example code:
trait Wrapper {
type Implementation
implicit val instance: Data[Implementation]
}
trait Data[A] {
def create : A
}
object DataInstances {
implicit object IntData extends Data[Int] { def create = 0}
implicit object StringData extends Data[String] { def create = "<empty>"}
implicit object FloatData extends Data[Float] { def create = 0.5F}
}
import DataInstances._
object IntWrapper extends Wrapper { type Implementation = Int; implicit val instance = IntData }
object StringWrapper extends Wrapper { type Implementation = String; implicit val instance = StringData}
object FloatWrapper extends Wrapper { type Implementation = Float; implicit val instance = FloatData}
object Test extends App {
def run[W <: Wrapper, D](wrapper: W)(implicit data: Data[D], ev: D =:= W#Implementation) : D = {
data.create
}
run(StringWrapper)
}
and here I get a compilation error:
Error:(31, 6) ambiguous implicit values:
both object IntData in object DataInstances of type DataInstances.IntData.type
and object StringData in object DataInstances of type DataInstances.StringData.type
match expected type Data[D]
run(StringWrapper)
^
Can you explain me why the compiler finds it ambiguous? From what I can tell (and what I tried to express) is that when I pass StringWrapper
then, according to type equality evidence the only possible value for D
would be String
and therefore the only possible value for data
would be StringData
.
But obviously the compiler doesn't think so :)
And what would be the way to express this constraint properly?
I don't see a reason to introduce type D in method run. Without it method signature looks simpler and successfully compiles
def run[W <: Wrapper](wrapper: W)(implicit data: Data[W#Implementation]) : W#Implementation = {
data.create
}
+++
btw, if you change order of implicits in your original method it will compile too, looks like 'ev' help to "type-bound" implicit resolution for data
def run[W <: Wrapper, D](wrapper: W)(implicit ev: D =:= W#Implementation, data: Data[D]) : D = {
data.create
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.