Question

Disclaimer: This is a question of what is possible, not what would be recommended in practice.

Let's say you're given the following classes:

case class point1(x: Int, y:Int)
case class point2(x: Int, y:Int)
case class point3(x: Int, y:Int)

and you have lists containing some number of each class

val points1 = List[point1](/*Can be empty for this example*/)
val points2 = List[point2]()
val points3 = List[point3]()

is it possible to create a list of a structural type that can contain all three point types using the usual techniques like ++, :::, or .union(..) without defining a common trait that all the classes extend, i.e.

var points: List[{def x: Int; def y: Int}] = 
    points1 ::: points2 ::: points3

I understand that as written above, the ::: operator returns a List[Product]. I assume it's a matter of providing the right hints to the Scala compiler, because the following code does produce a list of the correct type:

var points: ListBuffer[{def x: Int; def y: Int}] = List[{def x: Int; def y: Int}]()
points1.foreach( e => {
    val p: {def x: Int; def y: Int} = e;
    points.append(p);
})
points2.foreach( e => {
    val p: {def x: Int; def y: Int} = e;
    points.append(p);
})

Are there any hints I can give to help the Scala compiler to select the correct type for ::: and produce a List of the structural type specified?

Was it helpful?

Solution

(points1 : List[{val x : Int; val y : Int}]) ::: points2 ::: points3

Should work!

OTHER TIPS

If you want to write the following code:

var points: List[{def x: Int; def y: Int}] = 
points1 ::: points2 ::: points3

It works:

implicit def typer[B >: A, A <: { def x: Int; def y: Int }](t: List[B]): List[A] = t

var points: List[{def x: Int; def y: Int}] = 
points1 ::: points2 ::: points3
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top