Aquí hay una configuración simple con dos rasgos, una clase con un parámetro de tipo covariante delimitado por los rasgos anteriores y una segunda clase con un parámetro de tipo delimitado por la otra clase. Para ambas clases, un método particular está disponible (a través de evidencia implícita) solo si uno de los dos rasgos subyace en el parámetro de tipo. Este compila bien:Scala: evidencia implícita para la clase con el parámetro de tipo
trait Foo
trait ReadableFoo extends Foo {def field: Int}
case class Bar[+F <: Foo](foo: F) {
def readField(implicit evidence: F <:< ReadableFoo) = foo.field
}
case class Grill[+F <: Foo, +B <: Bar[F]](bar: B) {
def readField(implicit evidence: F <:< ReadableFoo) = bar.readField
}
Sin embargo, desde Bar
es covariante en F
, no debería necesitar el parámetro F
en Grill
. Solo debo exigir que B
sea un subtipo de Bar[ReadableFoo]
. Esto, sin embargo, falla:
case class Grill[+B <: Bar[_]](bar: B) {
def readField(implicit evidence: B <:< Bar[ReadableFoo]) = bar.readField
}
con el error:
error: Cannot prove that Any <:< this.ReadableFoo.
def readField(implicit evidence: B <:< Bar[ReadableFoo]) = bar.readField
¿Por qué no se están tomando las pruebas implícita en cuenta?
No estoy seguro de si <:
Kaito
@Kaito: ¿Tiene alguna evidencia de que '<: <' s 'apply' no se llame? Es [comportamiento documentado] (http://www.scala-lang.org/api/rc/scala/Predef$$$less$colon$less.html). Podrías escribir '(bar: Bar [ReadableFoo])., ReadField' y dejar que la conversión implícita se active automáticamente, pero la versión de Sciss me parece más limpia. –
@TravisBrown: ninguna. Pero no puedo encontrar la línea que en realidad documenta verbalmente el comportamiento de la función, solo la explicación heredada del rasgo abstracto de Function1. Estoy de acuerdo en que es bueno, pero no estoy seguro si se puede confiar en ese comportamiento, también podría arrojar una excepción en la próxima versión, creo. – Kaito