In a previous question I had some issues with Union type not generating
warnings consistently during pattern matching. I now have an example were
the Iterator.sliding
method does not result in the expected type.
Lets assume I have a container classes that wrap a primitive type as follows:
sealed trait VarValues[T, C <: VarValues[T,C]] {
this: C =>
val arr: Array[T]
}
final case class VarDoubles(arr: Array[Double]) extends VarValues[Double, VarDoubles]
final case class VarInts(arr: Array[Int]) extends VarValues[Int, VarInts]
final case class VarStrs(arr: Array[String]) extends VarValues[String, VarStrs]
Also assume that I use a type alias so:
type Numeric = Double | Int
Now my objective s to match on VarValues[_,_]
so that I can determine how to process data.
This method compiles cortectly:
def check4(a: VarValues[_,_], b: VarValues[_,_]): Unit = {
(a,b) match {
case (x:(VarDoubles|VarInts), y:(VarDoubles|VarInts)) =>
val x0: Iterator[Numeric] = x.arr.iterator
//val y0: Iterator[Numeric] = y.arr.iterator
val y0 = y.arr.iterator
val l0: Iterator[(Numeric, Numeric)] = x0.zip(y0)
val ll0: Iterator[(Numeric, Numeric)]#GroupedIterator[(Numeric, Numeric)] = x0.zip(y0).sliding(2,1)
???
case _ => ???
}
}
However if I use the fully typed val y0: Iterator[Numeric] = y.arr.iterator
instead of the
un-typed one, I get an error in the line that declares ll0
only. It seems like an AnyVal
is now expected,
and not a Numeric
. Here is an example of the error.
[error] 110| val ll0: Iterator[(Numeric, Numeric)]#GroupedIterator[(Numeric, Numeric)] = x0.zip(y0).sliding(2,1)
[error] | ^^^^^^^^^^^^^^^^^^^^^^^
[error] |Found: Iterator[(gg.SlidingIssue.Numeric, AnyVal)]#GroupedIterator[(
[error] | gg.SlidingIssue.Numeric
[error] |, AnyVal)]
[error] |Required: Iterator[(gg.SlidingIssue.Numeric, gg.SlidingIssue.Numeric)]#GroupedIterator[(
[error] | gg.SlidingIssue.Numeric
[error] |, gg.SlidingIssue.Numeric)]
[error] one error found
Could this be some issue with the type alias? So I tried:
def check5(a: VarValues[_,_], b: VarValues[_,_]): Unit = {
(a,b) match {
case (x:(VarDoubles|VarInts), y:(VarDoubles|VarInts)) =>
val x0: Iterator[Double|Int] = x.arr.iterator
//val y0: Iterator[Double|Int] = y.arr.iterator
val y0 = y.arr.iterator
val l0: Iterator[(Double|Int, Double|Int)] = x0.zip(y0)
val ll0: Iterator[(Double|Int, Double|Int)]#GroupedIterator[(Double|Int, Double|Int)] = x0.zip(y0).sliding(2,1)
???
case _ => ???
}
}
but get the same results. However if I try:
def check6(a: VarValues[_,_], b: VarValues[_,_]): Unit = {
(a,b) match {
case (x:VarDoubles, y:VarDoubles) =>
val x0: Iterator[Double] = x.arr.iterator
val y0: Iterator[Double] = y.arr.iterator
val l0: Iterator[(Double, Double)] = x0.zip(y0)
val ll0: Iterator[(Double, Double)]#GroupedIterator[(Double, Double)] = x0.zip(y0).sliding(2,1)
???
case _ => ???
}
}
it compiles as expected.
So it seems like the use of a type alias with Union types seems to have some unexpected
results - at least for me. Can anyone tell me if this is incorrect behavior or I am just using
this new construct incorrectly.
TIA.