Я бы хотел иметь возможность в общем манипулировать типами, такими как T[_] <: Traversable
, чтобы я мог делать такие вещи, как отображение и фильтрация, но я бы хотел отложить решение о том, какой Traversable
я выберу, как можно дольше .
Я хотел бы иметь возможность писать функции для обобщенного T[Int]
, который возвращает T[Int]
, а не Traversable[Int]
. Например, я хотел бы применить функцию к Set[Int]
или Vector[Int]
или ко всему, что расширяет Traversable, и вернуть этот тип обратно.
Сначала я попытался сделать это простым способом, например:
trait CollectionHolder[T[_] <: Traversable[_]] {
def easyLessThanTen(xs: T[Int]): T[Int] = {
xs.filter(_ < 10)
}
}
но это не скомпилируется: отсутствует тип параметра для расширенной функции. Однако он скомпилируется, если функция принимает Traversable[Int]
вместо T[Int]
, поэтому я подумал, что могу работать с Traversable
и преобразовать в T
. Это привело меня к CanBuildFrom
object DoingThingsWithTypes {
trait CollectionHolder[T[_] <: Traversable[_]] {
def lessThanTen(xs: T[Int])(implicit cbf: CanBuildFrom[Traversable[Int], Int, T[Int]]): T[Int] = {
val filteredTraversable = xs.asInstanceOf[Traversable[Int]].filter(_ < 10)
(cbf() ++= filteredTraversable).result
}
, который компилируется. Но тогда в моих тестах:
val xs = Set(1, 2, 3, 4, 1000)
object withSet extends CollectionHolder[Set]
withSet.lessThanTen(xs) shouldBe Set(1, 2, 3, 4)
Я получаю следующую ошибку компилятора:
Невозможно создать коллекцию типа Set [Int] с элементами типа
Int основано на коллекции типа Traversable [Int]. недостаточно
аргументы для метода lessThanTen: (неявный cbf:
scala.collection.generic.CanBuildFrom [Traversable [Int], Int, Set [Int]]) Установите [Int].
Не указано значение параметра cbf.
Где я могу получить CanBuildFrom для этого преобразования? Или еще лучше, как я могу изменить свой более простой подход для достижения желаемого результата? Или мне нужно использовать класс типов и написать неявную реализацию для каждого Traversable, который я хочу использовать (один для Set, один для Vector и т. Д.)? Я предпочел бы избежать последнего подхода, если это возможно.