Ich habe einige Probleme mit Typklassen in Scala und genauer mit Fehlern zur Kompilierzeit, wenn eine Typklasseninstanz nicht gefunden werden kann. Nehmen wir an, ich habe eine Typklasse TC
und ein Objekt B[C]
, das eine Instanz von TC
nur dann hat, wenn C
eine Instanz von TC
hat. In Scala kann dies implicit def btc[C](implicit ctc: TC[C]) = new TC[B[C]] { ... }
geschrieben werden. Wenn Sie eine TC[B[C]]
für eine C
benötigen, für die scalac keine Instanz TC[C]
finden kann, gibt scalac eine Fehlermeldung aus, dass es keine TC[B[C]]
finden kann. Obwohl dies der Fall ist, fehlt in der Fehlermeldung der Grund, warum scalac TC[B[C]]
nicht finden kann, dh TC[C]
kann nicht gefunden werden.Scalas implicitNotFound Annotation präzisieren
das Problem zu veranschaulichen, habe ich beschlossen, ein kleines Spielzeug Beispiel zu machen, wo TC
PrettyPrintable
ist, C
ist Unit
und B
ist Option
:
import scala.annotation.implicitNotFound
@implicitNotFound("Cannot pretty print instances of the type ${T}")
trait PrettyPrintable[T] {
def prettyPrint(t: T): String
}
object PrettyPrintable {
def apply[T](implicit pp: PrettyPrintable[T]): PrettyPrintable[T] = pp
implicit def optPP[T](implicit opp: PrettyPrintable[T]) = new PrettyPrintable[Option[T]] {
override def prettyPrint(ot: Option[T]): String = ot.fold("")(opp.prettyPrint)
}
}
object Main extends App {
println(PrettyPrintable[Option[Unit]].prettyPrint(None)) // error
}
Wenn ich die Anwendung ausführen, bekomme ich die Fehlermeldung:
[error] /home/rief/prog/scala/implicitNotFoundTest/Main.scala:24: Cannot pretty print instances of the type Option[Unit]
[error] println(PrettyPrintable[Option[Unit]].prettyPrint(None))
Das ist natürlich wahr: scalac findet keine schöne Druckinstanz für den Typ Option[Unit]
. Das Problem ist, dass der Fehler selbst nicht sehr hilfreich ist, weil der Punkt nicht ist, dass scalac eine Instanz der Typklasse nicht finden kann, sondern mehr, warum sie es nicht finden kann. In diesem Fall liegt der Grund, warum Option[Unit]
keine hübsche Druckinstanz hat, darin, dass Unit
keine hübsche Druckinstanz hat, aber für komplexere Fälle kann dies ein Albtraum sein.
Meine Frage ist: Ist es möglich, Fehler implizit nicht genauer zu finden?
Das ist ein gutes ist. Ich hatte einmal darüber nachgedacht, welchen Kontext ich einem Interpolator für die Annotationskette zur Verfügung stellen sollte, aber ich hatte nicht über implizite Suchhistorie nachgedacht. https://issues.scala-lang.org/browse/SI-7411 –