Reputation: 6064
Is there a generic way to force SeqView to Seq?
In Scala 2.12, SeqView extends Seq, so you can end up with laziness when one might want strict collections.
I was trying to generically force SeqViews to Seqs, but am running into type errors that I'm not familiar with:
import scala.collection.SeqView
def force(xs: Seq[Int]): Seq[Int] = xs match {
case view: SeqView[_,_] => view.force
case other => other
}
force(List(1, 2, 3))
force(List(1, 2, 3).view)
Cannot construct a collection of type That with elements of type _ based on a collection of type _.
Scastie link: https://scastie.scala-lang.org/ThMW8jixT7Odet17EiDavA
Notably, I can provide type parameters to the match, but of course, I get type erasure warnings
import scala.collection.SeqView
def force(xs: Seq[Int]): Seq[Int] = xs match {
case view: SeqView[Int, Seq[Int]] => view.force
case other => other
}
force(List(1, 2, 3))
force(List(1, 2, 3).view)
The type erasure warning scares me, but it seems to work.
Can anyone shed some light on this?
Upvotes: 1
Views: 204
Reputation: 22595
By using Seq[_,_]
in patten matching you made compiler unable to find right implicit for type class CanBuildFrom
.
The workaround I came up with, to not have a warning and allow compiler resolve CanBuildFrom
is just to match against SeqView[_, _]
and then use asInstanceOf
to return to original type:
import scala.collection.SeqView
def force[A](xs: Seq[A]): Seq[A] = xs match {
case view: SeqView[_, _] => view.asInstanceOf[SeqView[A, Seq[A]]].force
case other: Seq[A] => other
}
println(force(List(1, 2, 3)))
println(force(List(1, 2, 3).view))
I also added the type parameter A
instead of fixed Int
.
Another possibility is just to annotate types with @unchecked
:
def force[A](xs: Seq[A]): Seq[A] = xs match {
case view: SeqView[A@unchecked, Seq[A]@unchecked] => view.force
case other: Seq[A] => other
}
Upvotes: 2