Specific Builder for Parameterized Type

大兔子大兔子 提交于 2020-01-01 06:12:30

问题


I'm trying to write a class in scala that wraps a (parameterized) collection and overrides it's foreach method. What it does with the foreach method is unimportant for the purpose of this question, so lets say it just prints each element out as it's visited. So ideally, we'd be able to use the wrapper as follows:

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

The key is that I want this to work with any iterable; not just a list. So my first attempt was something like what follows

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) }
        }  
 }

However, for this class to be concrete, we need an iterator method and a newBuilder method. The iterator method is no problem, we can just "steal" s's iterator like so:

override def iterator = s.iterator

The problem is when I try to define newBuilder. I need the builder to return an S[A]. However, S[A] is a parameterized collection that is bounded by Iterable[A]. Thus all of my attempts using genericBuilder or getting the companion object's builder result in an Iterable[A] rather than an S[A], with the corresponding error messages

[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 

How can I obtain a builder that builds the specific type, S[A], rather than the generic bounded type Iterable[A]? Is this even possible? Any help in understanding the idiomatic Scala way to do this (or any way that actually works) would be greatly appreciated!


回答1:


IterableLike (and the other XxxLike traits) abstract over the return type by delegating to a Builder that has to be specific for each collection type. Hence what you are trying cannot work.

You could create a generic wrapper MyWrapperLike[A, B] and a couple of specific wrappers MySeqWrapper[A] extends MyWrapperLike[A, Seq[A]] (same for Set, Map, List, etc.), i.e. mimic the design of the Scala collection library.



来源:https://stackoverflow.com/questions/9084713/specific-builder-for-parameterized-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!