Gram z wzorem typeclass w Scali, ale nie byłem w stanie wymyślić, jak zaimplementować niejawny obiekt towarzyszący, gdy typ, z którym pracuję jest generyczny.Scala Typeclasses z generics
Na przykład, powiedzmy, że zdefiniowałem cechę dla czcionki typograficznej, która zapewnia funkcje do umieszczania rzeczy w 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)
To działa zgodnie z oczekiwaniami, pozwalając mi dostarczyć implementacje Boxer
dla różnych typów. Mam jednak pomysł, jak to zrobić, gdy typ, na którym chcę działać, jest generyczny. Powiedzmy, że chciałem móc użyć mojego Boxer
na dowolnym Seq[A]
. object
s Scala nie może zawierać parametry typu, więc jestem ze stratą dla gdzie iść:
// 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
}
Czy istnieje jakiś sposób, aby wspierać niejawne konwersje typów generycznych bez konieczności niejawny oddzielny obiekt dla każdy typ wewnętrzny?
Ah! Całkowicie zapomniałem o różnicy między 'def foo: A' i' def foo(): A'. To naprawdę oczyszcza rzeczy! – KChaloux