Конкретный конструктор для параметризованного типа - PullRequest
4 голосов
/ 31 января 2012

Я пытаюсь написать класс в scala, который оборачивает (параметризованную) коллекцию и переопределяет ее метод foreach. То, что он делает с методом foreach, не имеет значения для целей этого вопроса, поэтому предположим, что он просто печатает каждый элемент по мере его посещения. Поэтому в идеале мы можем использовать упаковщик следующим образом:

scala> val a = List(1,2,3,4,5)
scala> val b = MyWrapper(a)
scala> b.foreach{ x => x }
1
2
3
4
5

Ключ в том, что я хочу, чтобы это работало с любой итерацией; не просто список. Итак, моя первая попытка была похожа на следующее

class MyWrapper[A, S[A] <: Iterable[A]]( val s: S[A] with IterableLike[A, S[A]]) 
      extends IterableLike[A, S[A]] {

        override def foreach[U](f: A => U): Unit = {
          iterator.foreach{ x => println(x); f(x) }
        }  
 }

Однако, чтобы этот класс был конкретным, нам нужен метод итератора и метод newBuilder. Метод итератора не проблема, мы можем просто «украсть» итератор s следующим образом:

override def iterator = s.iterator

Проблема в том, когда я пытаюсь определить newBuilder. Мне нужен строитель, чтобы вернуть S [A]. Тем не менее, S [A] является параметризованной коллекцией, которая ограничена Iterable [A]. Таким образом, все мои попытки использования genericBuilder или получения компоновщика объекта-компаньона приводят к Iterable [A], а не к S [A], с соответствующими сообщениями об ошибках

[error] method newBuilder in trait TraversableLike of type => scala.collection.mutable.Builder[A,S[A]] is not defined
[error] method seq in trait Parallelizable of type => scala.collection.TraversableOnce[A] is not defined 

Как получить построитель, который создает определенный тип , S [A], а не общий ограниченный тип Iterable [A]? Это вообще возможно? Будем весьма благодарны за любую помощь в понимании идиоматического способа Scala сделать это (или любого другого способа, который действительно работает)!

1 Ответ

2 голосов
/ 31 января 2012

IterableLike (и другие XxxLike черты) абстрагируются по типу возвращаемого значения путем делегирования Builder , который должен быть специфичным для каждого типа коллекции.Следовательно, то, что вы пытаетесь, не может работать.

Вы можете создать универсальную оболочку MyWrapperLike [A, B] и несколько специальных оболочек MySeqWrapper [A] расширяет MyWrapperLike [A,Seq [A]] (то же самое для Set , Map , List и т. Д.), Т.е. имитировать дизайн библиотеки коллекции Scala.

...