Ho giocato con lo schema di classe in Scala, ma non sono stato in grado di capire come implementare l'oggetto associato implicito quando il tipo con cui sto lavorando è generico.Typeclasses Scala con generici
Ad esempio, supponiamo di aver definito un tratto per un typeclass che fornisce le funzioni per inserire le cose in Box
es.
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)
Questo funziona come previsto, che mi permette di fornire implementazioni di Boxer
di vari tipi. Tuttavia, ho no idea di come farei questo quando il tipo su cui vorrei agire è generico. Diciamo che volevo essere in grado di usare il mio Boxer
su qualsiasi Seq[A]
. object
s in Scala non possono includere parametri di tipo, quindi sono in perdita per dove andare:
// 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
}
Esiste un modo per sostenere conversioni implicite di tipi generici senza dover implicitamente un oggetto separato per ogni tipo interno?
Ah! Mi ero completamente dimenticato della differenza tra 'def foo: A' e' def foo(): A'. Questo chiarisce davvero le cose! – KChaloux