Ecco una semplice impostazione con due tratti, una classe con un parametro di tipo covariante limitato dai tratti precedenti e una seconda classe con un parametro di tipo limitato dall'altra classe. Per entrambe le classi, è disponibile un metodo particolare (tramite prove implicite) solo se uno dei due tratti è alla base del parametro type. Questo compila bene:Scala: Evidenza implicita per classe con parametro 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
}
Tuttavia, dal momento che Bar
è covariante nel F
, non avrei bisogno di parametro F
in Grill
. Dovrei semplicemente richiedere che B
sia un sottotipo di Bar[ReadableFoo]
. Questo, tuttavia, fallisce:
case class Grill[+B <: Bar[_]](bar: B) {
def readField(implicit evidence: B <:< Bar[ReadableFoo]) = bar.readField
}
con l'errore:
error: Cannot prove that Any <:< this.ReadableFoo.
def readField(implicit evidence: B <:< Bar[ReadableFoo]) = bar.readField
Perché non è la prova implicita di essere presi in considerazione?
io non sono sicuro se <: <è destinato a essere chiamato, è semplicemente un valore che esiste se il primo parametro è un sottotipo del secondo. L'implementazione è fondamentalmente la funzione di identità. Questi esempi funzionano perché fondamentalmente fanno un typecast (sicuro) che aiuta il compilatore a trovare il parametro implicito per il metodo readField. – Kaito
@Kaito: hai qualche prova che '<: <' 's apply non è stato chiamato? È [comportamento documentato] (http://www.scala-lang.org/api/rc/scala/Predef$$$less$colon$less.html). Potresti scrivere '(bar: Bar [ReadableFoo]). ReadField' e lasciare che la conversione implicita si avvii automaticamente, ma la versione di Sciss mi sembra più pulita. –
@TravisBrown: Nessuno. Ma non riesco a trovare la linea che in realtà documenta verbalmente il comportamento della funzione, solo la spiegazione ereditata del tratto astratto Function1. Sono d'accordo che è bello, ma non sono sicuro che si possa fare affidamento su questo comportamento, ma potrebbe anche essere un'eccezione nella prossima versione che penso. – Kaito