Причина, по которой аннотация типа требуется в
xss reduceLeft seqed[Int](_+_)
, но не в
xs zip ys map Function.tupled(_+_)
, связана с разницей в требованиях к типу между map
и reduceLeft
.
def reduceLeft [B >: A] (f: (B, A) ⇒ B): B
def map [B] (f: (A) ⇒ B): Seq[B] // simple version!
reduceLeft
ожидает, что seqed
вернет тип B
, где B >: Int
.Похоже, что точный тип для seqed
не может быть известен, поэтому мы должны предоставить аннотацию.Больше информации в этом вопросе .
Один из способов преодоления этого состоит в том, чтобы повторно внедрить reduceLeft
без нижней границы.
implicit def withReduceL[T](xs: Seq[T]) = new {
def reduceL(f: (T, T) => T) = xs reduceLeft f
}
Тест:
scala> Seq(Seq(1,2,3), Seq(2,2,2)) reduceL seqed(_+_)
res1: Seq[Int] = List(3, 4, 5)
Проблема в том, что теперь это не работает для подтипов Seq
(например, List
), с параметром [Int]
или без него:
scala> Seq(List(1,2,3), List(2,2,2)) reduceL seqed(_+_)
<console>:11: error: missing parameter type for expanded function ((x$1, x$2) => x$1.$plus(x$2))
Seq(List(1,2,3), List(2,2,2)) reduceL seqed(_+_)
^
reduceL
ожидает функцию типа (List[Int], List[Int]) => List[Int]
.Поскольку Function2
определяется как Function2 [-T1, -T2, +R]
, (Seq[Int], Seq[Int]) => Seq[Int]
не является допустимой заменой.