Below I have:
trait Elem {
def compare: Int
}
case class DiffElem(weight: Int, len: Int) extends Elem {
def compare = weight - len;
}
Now there can be many sub-classes of Elem, based on the compare function.
Now I have a function, that reads input from file and generates a list of DiffElem:
def getInput[T <: Elem](): List[T] = {
var ans: List[T] = List.empty[T]
for (line <- Source.fromFile("src/week1/jobs.txt").getLines()) {
val diff = line.split(" ")
ans = ans match{
case i:List[DiffElem] => new DiffElem(Integer.parseInt(diff(0)), Integer.parseInt(diff(1))) :: ans;
case _ => ???
}
}
ans
}
But the compiler does not allow the operation, obviously as :: follows contra-variance type and I am trying to do invariance. If I convert the function signature to T >: Elem then it works, but the purpose is not solved.
Any better approach??
If you’re constructing DiffElem inside getInput, then how (and why) do you want to get list of arbitrary T <: Elem? To do something like this, you should be able to convert from DiffElem to any another T <: Elem, and that convertability could be captured with implicit like this:
, but do you really want it? If you’ll be happy with just list of DiffElem’s, you could rewrite your function in functional style this way:
map is higher-order function that captures transformation of each element of sequence into the result of application of its funarg to this element.
Update:
To make modular type-driven list creation I’ll suggest implicits:
Now, for any E <: Elem, list of which you want to get, you should provide implicit value of type (Int, Int) => E into the scope, like:
And in any scope, where this implicit is visible, you could use getInput like this: