Тип вывод на анонимные функции с Enrich-MY-библиотеком
-
26-10-2019 - |
Вопрос
Скажите, что у меня есть метод, который превращает функцию на два элемента) в (функцию на двух последовательностях):
def seqed[T](f: (T,T) => T): (Seq[T], Seq[T]) => Seq[T] = (_,_).zipped map f
В словах, полученная функция занимает две последовательности xs
а также ys
, и создает новую последовательность, состоящую из (xs(0) f ys(0), xs(1) f ys(1), ...)
Так, например, если xss
является Seq(Seq(1,2),Seq(3,4))
а также f
является (a: Int, b: Int) => a + b
, мы можем вызвать это так:
xss reduceLeft seqed(f) // Seq(4, 6)
или с анонимной функцией:
xss reduceLeft seqed[Int](_+_)
Это довольно хорошо; Было бы неплохо избавиться от [Int]
Тип аргумента, но я не вижу, как (какие -либо идеи?).
Чтобы это было немного больше похоже на tupled
Метод, я также попробовал рисунок Enrich-My-Library:
class SeqFunction[T](f: (T,T) => T) {
def seqed: (Seq[T], Seq[T]) => Seq[T] = (_,_).zipped map f
}
implicit def seqFunction[T](f: (T,T) => T) = new SeqFunction(f)
Для предварительно определенной функции это отлично работает, но это уродливо с анонимными
xss reduceLeft f.seqed
xss reduceLeft ((_:Int) + (_:Int)).seqed
Есть ли другой способ переформулировать это, чтобы вывести типы, и я могу использовать синтаксис что -то вроде:
// pseudocode
xss reduceLeft (_+_).seqed // ... or failing that
xss reduceLeft (_+_).seqed[Int]
? Или я спрашиваю слишком много типового вывода?
Решение 3
Причина, по которой аннотация типа требуется в
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]
не является действительной заменой.
Другие советы
Вы не можете сделать это так, как хотите, но посмотрите на Function.tupled
, что является противоречивой .tupled
Это решает эту же проблему.
scala> List(1, 2, 3) zip List(1, 2, 3) map (_ + _).tupled
<console>:8: error: missing parameter type for expanded function ((x$1, x$2) => x$1.$plus(x$2))
List(1, 2, 3) zip List(1, 2, 3) map (_ + _).tupled
^
<console>:8: error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.$plus(x$2))
List(1, 2, 3) zip List(1, 2, 3) map (_ + _).tupled
^
scala> List(1, 2, 3) zip List(1, 2, 3) map Function.tupled(_ + _)
res7: List[Int] = List(2, 4, 6)
Я почти уверен, что ты находятся Слишком много спрашивает. Тип вывод в Scala идет слева направо, так что тип (_+_)
нужно выяснить сначала, прежде чем даже рассмотреть .sedeq
часть. И там недостаточно информации.