Hier ist ein einfacher Aufbau mit zwei Merkmalen, einer Klasse mit einem kovarianten Typparameter, der durch die vorherigen Eigenschaften begrenzt ist, und einer zweiten Klasse mit einem Typparameter, der von der anderen Klasse begrenzt wird. Für beide Klassen ist eine bestimmte Methode nur dann verfügbar (über implizite Beweise), wenn einer der beiden Merkmale dem Typparameter zugrunde liegt. Dies kompiliert fein:Scala: Impliziter Beweis für die Klasse mit dem Typparameter
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
}
Da jedoch Bar
covariant ist in F
, ich sollte die F
Parameter in Grill
nicht benötigen. Ich sollte nur verlangen, dass B
ist ein Untertyp von Bar[ReadableFoo]
. Dies ist jedoch nicht:
case class Grill[+B <: Bar[_]](bar: B) {
def readField(implicit evidence: B <:< Bar[ReadableFoo]) = bar.readField
}
mit dem Fehler:
error: Cannot prove that Any <:< this.ReadableFoo.
def readField(implicit evidence: B <:< Bar[ReadableFoo]) = bar.readField
Warum sind die impliziten Beweise nicht berücksichtigt werden?
Ich bin nicht sicher, ob <:
Kaito
@Kaito: Haben Sie irgendwelche Beweise, dass '<: <' '' apply'' nicht gemeint ist? Es ist [dokumentiertes Verhalten] (http://www.scala-lang.org/api/rc/scala/Predef$$$less$colon$less.html). Sie könnten '(bar: Bar [ReadableFoo]) .readField' schreiben und die implizite Konvertierung automatisch einleiten, aber Sciss 'Version fühlt sich für mich sauberer an. –
@TravisBrown: Keine. Aber ich kann nicht die Linie finden, die das Verhalten der Funktion verbal dokumentiert, sondern nur die vererbte Erklärung der abstrakten Eigenschaft Function1. Ich stimme zu, dass es nett ist, aber ich bin mir nicht sicher, ob dieses Verhalten zuverlässig ist, es könnte auch eine Ausnahme in der nächsten Version werfen, denke ich. – Kaito