Ich versuche, ein wenig anspruchsvolle Beispiel von typeclasses in Scala zu implementieren: konvertieren Wert des Typs T in String als Bibliothek implementiert ein Benutzer kann für jeden Typ T erweitert. Also hier ist das Merkmal alle typeclasses implementieren sollte: die Arbeit gehen zu nennenImportieren implicits aus einer Unterklasse
trait Printable[T] {
def asString(value: T): String
}
die Funktion, die wir zu tun: mit einer Reihe von typeclasses für einige Standardtypen
object Printer {
def print[T](value: T)(implicit p:Printable[T]): String = p.asString(value)
}
Object (nur int & lange hier zum Beispiel):
object SimpleFormats extends Formats
trait Formats {
implicit val intFormat = new Printable[Int] {
override def asString(value: Int) = value.toString
}
implicit val longFormat = new Printable[Long] {
override def asString(value: Long) = value.toString
}
}
Stellen Sie sich vor, dass der Benutzer unsere Bibliothek für einen anderen Typ wie Float und Double erweitern möchte. Er erstellt also ein anderes Objekt, indem es das erste untergliedert. Die Idee dabei ist, neue implizite Mitglieder an der Basis Objekt hinzufügen, so kann die Standardsammlung von typeclasses für beliebig viele Benutzer gelieferten Typen erweitert werden:
object ExtendedFormats extends Formats {
implicit val floatFormat = new Printable[Float] {
override def asString(value: Float) = value.toString
}
implicit val doubleFormat = new Printable[Double] {
override def asString(value: Double) = value.toString
}
}
Und schließlich die wichtigsten app unserer Bibliothek. Es gibt zwei Beispielfunktionen Operationen auf verschiedene Arten tun, so ist es nicht möglich, einzelne spezifische implizite Printer[T]
als liefern:
- gibt es mehrere Operationen auf mehrere Arten
- die
Printer
nicht vorher wissen, welche Arten zugeführt werden kann vom Benutzer.
So ist die Haupt-App sieht wie folgt aus:
object Example {
// compiles OK, uses only default typeclasses
def simpleExample(implicit formats: Formats) = {
import formats._
Printer.print(42) + Printer.print(24L)
}
// compilation failed, cannot find Printable[Float]
// uses user-supplied formats
def extendedExample(implicit formats: Formats) = {
import formats._
Printer.print(42f) + Printer.print(31337.0)
}
def main(args: Array[String]): Unit = {
implicit val formats = ExtendedFormats
println(simpleExample)
println(extendedExample)
}
}
Ich sehe, dass scala Compiler versucht implicits vom Formats
zu importieren, die Tatsache zu ignorieren, dass es ExtendedFormats
tatsächlich ist.
Fragen:
- Gibt es eine Möglichkeit implicits von einer Unterklasse zu importieren, wie im Beispiel beschrieben?
- Gibt es eine bessere Lösung für eine Charge von benutzerdefinierten Typklassen?
Sie können in [Simulacrum] (https://github.com/mpilquist/simulacrum) nach Typklassen suchen. –