How to create custom Seq with parameter of limited type in Scala?

Consider the following working user Seq:

class MySeq[B](val s: Seq[B]) 
extends Seq[B]
with GenericTraversableTemplate[B, MySeq]
with SeqLike[B, MySeq[B]] {
  override def companion = MySeq

  def iterator = s.iterator

  def apply(i: Int) = s(i)

  def length = s.length

  override def toString = s map { _.toString } mkString("\n")
}
object MySeq extends SeqFactory[MySeq] {
  implicit def canBuildFrom[B]: CanBuildFrom[Coll, B, MySeq[B]] =
       new GenericCanBuildFrom[B]
  def newBuilder[B] = new ListBuffer[B] mapResult (x => new MySeq(x.toSeq))
}

I would like to impose a restriction on the type parameter B. In other words, I would like something like this (doesn't work):

class MyA

class MySeq[+B <: MyA](val s: Seq[B]) 
extends Seq[B]
with GenericTraversableTemplate[B, MySeq]
with SeqLike[B, MySeq[B]] {
  override def companion = MySeq  // Type Mismatch Here

  def iterator = s.iterator

  def apply(i: Int) = s(i)

  def length = s.length

  override def toString = s map { _.toString } mkString("\n")
}
object MySeq extends SeqFactory[MySeq] {
  implicit def canBuildFrom[B]: CanBuildFrom[Coll, B, MySeq[B]] =
       new GenericCanBuildFrom[B]
  // Type Mismatch in the line below
  def newBuilder[B] = new ListBuffer[B] mapResult (x => new MySeq(x.toSeq))
}

But in these lines, the following type mismatch errors occur:

inferred type arguments [B] do not conform to 
class MySeq type parameter bounds [+B <: MyA] 
Main.scala  line 49

type mismatch;  
found   : countvotes.structures.MySeq.type  
required: scala.collection.generic.GenericCompanion[Seq]    
Main.scala  line 36

type mismatch;  
found   : MySeq[B(in class MySeq)]  
required: MySeq[B(in method newBuilder)]    
Main.scala  line 49

type mismatch;  
found   : scala.collection.immutable.Seq[B(in method newBuilder)]  
required: Seq[B(in class MySeq)]    
Main.scala  line 49

I tried to solve this problem by adding restrictions on parameters like CanBuildFrom and newBuilder, but then I get other error messages.

How to create a custom Seqbinding to a type parameter?

+4
source share
2 answers

I do not get the error on line 26:

override def companion = MySeq

Perhaps something else is causing this.

, , GenericCompanion[MySeq] ( SeqFactory). , GenericCompanion[Coll] , Coll[A] A (. newBuilder). MySeq[A] <: GenericTraversableTemplate[A, MySeq], genericBuilder . ; MySeq " ", , MyA.

, MySeq[B] <: GenericTraversableTemplate[B, Seq] ( extends Seq). companion. Seq, s.companion. ((as: MySeq[A]): Seq[A]).map(...) List ( , compiletime Seq). , as.s ( , , compiletime Seq). extends SetLike.

CanBuildFrom: MySeq.canBuildFrom[A <: MyA]: CanBuildFrom[MySeq[A], A, MySeq[A]] MySeq#newBuilder.

class MySeq[+B <: MyA](val s: Seq[B]) 
  extends Seq[B]
  with SeqLike[B, MySeq[B]]
{
  override def iterator = s.iterator
  override def apply(i: Int) = s(i)
  override def length = s.length

  override def toString = s.map(_.toString).mkString("\n")

  override def companion = s.companion
  protected[this] override def newBuilder: mutable.Builder[B, MySeq[B]] = new mutable.Builder[B, MySeq[B]] {
    private[this] val base = s.genericBuilder[B]
    override def +=(elem: B) = { base += elem; this }
    override def clear() = base.clear()
    override def result() = new MySeq[B](base.result())
  }
}

object MySeq {
  implicit def canBuildFrom[A <: MyA]: CanBuildFrom[MySeq[_], A, MySeq[A]] = ???
}

val list = List(new MyA, new MyA, new MyA, new MyA)
val vect = list.toVector
val mLst = new MySeq(list)
val mVec = new MySeq(vect)
{
  val res = mLst.filter(_.hashCode != list.head.hashCode)
  implicitly[res.type <:< MySeq[MyA]]
}
{
  val res = (mVec: Seq[MyA]).map(identity)
  assert(res.isInstanceOf[Vector[_]])
}
{
  val res = (mLst: Seq[MyA]).map(identity)
  assert(res.isInstanceOf[List[_]])
}
+2

MWE, HTNW , canBuildFrom :

class MyA

class MySeq[+A <: MyA](val s: Seq[A]) 
  extends Seq[A]
  with SeqLike[A, MySeq[A]]
{
  override def iterator = s.iterator
  override def apply(i: Int) = s(i)
  override def length = s.length

  override def toString = s.map(_.toString).mkString("\n")

  override def companion = s.companion
  protected[this] override def newBuilder = MySeq.newBuilder
}

object MySeq {
  def newBuilder[A <: MyA] = new mutable.Builder[A, MySeq[A]] {
    private[this] val base = Seq.newBuilder[A]
    override def +=(elem: A) = { base += elem; this }
    override def clear() = base.clear()
    override def result() = new MySeq[A](base.result())
  }

  implicit def canBuildFrom[A <: MyA]: CanBuildFrom[MySeq[_], A, MySeq[A]] = new CanBuildFrom[MySeq[_], A, MySeq[A]] {
    def apply(from: Election[_]) = newBuilder
    def apply() = newBuilder
  }
}
0

Source: https://habr.com/ru/post/1685348/


All Articles