Создание неявной функции, которая оборачивает map() в Scala с правильным типом: не для слабонервных
Я пытаюсь реализовать неявную функцию mapMetered
это обертывания map
и функции точно так же, как это с точки зрения возвращения правильного типа. Я попробовал это:
implicit class MeteredGenTraversablePimp[T, C[T] <: GenTraversable[T]](trav: C[T]) {
def foreachMetered(m: Meter)(f: T => Unit) =
m.foreach(trav)(f)
def mapMetered[B, That](m: Meter)(f: (T) => B)(
implicit bf: CanBuildFrom[C[T], B, That]
): That = {
m.start()
try {
trav.map { x =>
val z = f(x)
m.item_processed()
z
} (bf)
} finally { m.finish() }
}
}
Но когда я пытаюсь это сделать, я получаю сообщение об ошибке:
[info] Compiling 1 Scala source to /Users/benwing/devel/textgrounder/target/classes...
[error] /Users/benwing/devel/textgrounder/src/main/scala/opennlp/textgrounder/util/metering.scala:223: type mismatch;
[error] found : scala.collection.generic.CanBuildFrom[C[T],B,That]
[error] required: scala.collection.generic.CanBuildFrom[scala.collection.GenTraversable[T],B,That]
[error] } (bf)
[error] ^
[error] one error found
Есть похожие вопросы о переполнении стека, в том числе от Даниэля Собрала, который предлагает написать (trav: C[T] with GenTraversableLike[T])
но это не решает проблему.
1 ответ
Решение
Repr
параметр в CanBuildFrom
и в *Like
Типы коллекций уже существуют, чтобы представлять наиболее точный тип коллекции. Решение вашей проблемы - завернуть GenTraversableLike[A,Repr]
вместо C[T]
, Компилятор выведет точный тип как Repr
и все будет работать без нареканий
implicit class MeteredGenTraversablePimp[A, Repr](trav: GenTraversableLike[A,Repr]) {
def foreachMetered(m: Meter)(f: A => Unit) = {
m.start()
try {
trav.foreach{ e => f( e ); m.item_processed() }
} finally {
m.finish()
}
}
def mapMetered[B, That](m: Meter)(f: A => B)(
implicit bf: CanBuildFrom[Repr, B, That]
): That = {
m.start()
trav.map { x: A =>
try {
val z: B = f(x)
m.item_processed()
z
} finally { m.finish() }
}(bf)
}
}