Ich habe mit dem Typklassenmuster in Scala gespielt, aber ich konnte nicht herausfinden, wie das implizite Companion-Objekt implementiert wird, wenn der Typ, mit dem ich arbeite, generisch ist.Scala Typeclasses mit Generics
Zum Beispiel, ich habe ein Merkmal für eine Klasse definiert, die Funktionen zum Einfügen von Dingen in Box
es bietet.
case class Box[A](value: A)
trait Boxer[A] {
def box(instance: A): Box[A]
def unbox(box: Box[A]): A
}
implicit object IntBoxer extends Boxer[Int] {
def box(instance: Int) = Box(instance)
def unbox(box: Box[Int]) = box.value
}
def box[A : Boxer](value: A) = implicitly[Boxer[A]].box(value)
def unbox[A : Boxer](box: Box[A]) = implicitly[Boxer[A]].unbox(box)
Dies funktioniert wie erwartet, so dass ich Implementierungen von Boxer
für verschiedene Typen zur Verfügung zu stellen. Allerdings habe ich keine Idee, wie ich dies tun würde, wenn der Typ, auf den ich handeln möchte, selbst generisch ist. Nehmen wir an, ich wollte meine Boxer
auf jedem Seq[A]
verwenden können. object
s in Scala nicht Typparametern umfassen, so dass ich bei einem Verlust bin für wohin sie gehen:
// Will not compile - object cannot have type arguments
implicit object SeqBoxer[A] extends Boxer[Seq[A]] { ... }
// Will not compile - 'A' is unrecognized
implicit object SeqBoxer extends Boxer[Seq[A]] { ... }
// Compiles but fails on execution, as this doesn't implement an implicit
// conversion for _specific_ instances of Seq
implicit object SeqBoxer extends Boxer[Seq[_]] {
def box(instance: Seq[_]) = Box(instance)
def unbox(box: Box[Seq[_]]) = box.value
}
// Will not compile - doesn't technically implement Boxer[Seq[_]]
implicit object SeqBoxer extends Boxer[Seq[_]] {
def box[A](instance: Seq[A]) = Box(instance)
def unbox[A](box: Box[Seq[A]]) = box.value
}
// Compiles, but won't resolve with 'implicitly[Boxer[Seq[Foo]]]'
// I had high hopes for this one, too :(
implicit def seqBoxer[A]() = new Boxer[Seq[A]] {
def box(instance: Seq[A]) = Box(instance)
def unbox(box: Box[Seq[A]]) = box.value
}
Gibt es eine Möglichkeit implizite Konvertierungen von generischen Typen zu unterstützen, ohne jede für zu impliziten ein separates Objekt mit interner Typ?
Ah! Ich habe den Unterschied zwischen 'def foo: A' und' def foo(): A' total vergessen. Das räumt wirklich auf! – KChaloux