Jack Koenig
Jack Koenig

Reputation: 6064

Generically Force SeqView to Seq, Scala 2.12

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

Answers (1)

Krzysztof Atłasik
Krzysztof Atłasik

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

Related Questions