Chcę określić typ klasy tak:Problemy z kontrawariancji w Scala
trait CanFold[-T, R] {
def sum(acc: R, elem: T): R
def zero: R
}
implicit object CanFoldInts extends CanFold[Int, Int] {
def sum(x: Int, y: Int) = x + y
def zero = 0
}
implicit object CanFoldSeqs extends CanFold[Traversable[_], Traversable[_]] {
def sum(x: Traversable[_], y: Traversable[_]) = x ++ y
def zero = Traversable()
}
def sum[A, B](list: Traversable[A])(implicit adder: CanFold[A, B]): B =
list.foldLeft(adder.zero)((acc,e) => adder.sum(acc, e))
Jednak problemem jest to, kiedy to zrobić otrzymuję Traversable[Any]
i byłoby miło dostać Traversable[Int]
zamiast :
scala> sum(List(1,2,3) :: List(4, 5) :: Nil)
res10: Traversable[Any] = List(1, 2, 3, 4, 5)
Co gorsza, nie mogę zdefiniować niejawna dla Traversable[Int]
po zdefiniowaniu jeden dla Traversable[_]
, bo wtedy definicje by c ause niejednoznaczność. Po wyjęciu włosów straciłem.
Czy istnieje sposób, w jaki mogę zwrócić tę kwotę zamiast zamiast Traversable[Any]
?
Patrząc jak sum()
jest zdefiniowana na Seq
w bibliotece Scala, widzę, że działa z Numeric
, która jest niezmienna, ale chcę implementacje domyślne supertypes io wynik będzie inny niż wejście (tak samo jako krotność pracy) jest fajne.
Oh wow, i że działa! ... jednak jest to def, które zwraca instancję cechy, którą chcesz i miałem wrażenie, że niejawne params muszą być konkretnymi instancjami ... to jest niesamowite :-) –
, więc dlaczego 'def' działa i' niejawny obiekt' nie? – goral
@goral: Ponieważ 'object' nie może przyjmować parametrów typu. – sschaef