Reputation: 1178
Consider SubFoo extends Foo . I have a construct like this
trait SomeTrait
{
def someFun(a : List[Foo], ...) -> List[Foo]
.
.
.
}
Now in my code I would like to do y:List[SubFoo] = someFun(List(x),...) where x:SubFoo and y should be of type List[SubFoo]. But I get the error message expected List(SubFoo), actual: List(Foo): - How do I do that with the following constraints:-
I don't want to add a type parameter to SomeTrait ( like SomeTrait[+A]) because SomeTrait is used widely in our codebase without passing any types.
I wouldn't like to change y:List[SubFoo] to List[Foo] . I am looking for a solution that does the required change where someFun is defined.
The most obvious : do not change someFun to someFun(a : List[SubFoo], ...) -> List[SubFoo] . Nada
Let me know if there is a solution respecting the constraints or which at-least satisfies constraint-1.
Thanks
Upvotes: 0
Views: 213
Reputation: 78409
As mentioned in the comments, variance is not your way. Lists are covariant.
Without knowing more about your problem, it sounds like you're trying get a sublist of Some[Foo]
, where the sublist consists entirely of SubFoo
s.
So given
sealed trait Foo
case class SubFoo(baz: Int) extends Foo
case class OtherSubFoo(bam: String) extends Foo
it sounds like you would want a list of
List(SubFoo(1), SubFoo(2), OtherSubFoo("a"), SubFoo(25)): List[Foo]
to be converted to
List(SubFoo(1), SubFoo(2), SubFoo(25)): List[SubFoo]
Type signatures exist for a reason. If you're trying to convert a List[Foo]
to a List[SubFoo]
, you need your conversion function type to reflect that. Here is something you could potentially do:
trait SomeTrait {
def someFun(foos: List[Foo]): List[SubFoo] = {
val listOfSubFoos = foos.map {
case (sub: SubFoo) => Some(sub)
case _ => None
}
// now you have a list of type List[Option[SubFoo]],
// and want to flatten it to a List[SubFoo]
listOfSubFoos.flatten
}
}
There would be other ways to structure it, but the core idea here is that you'd need a function that reduces a List[Foo]
to a List[SubFoo]
. You can't have a type List[Foo]
and guarantee that every Foo
is a SubFoo
in the type system. If you need something like that, you'd most likely have to rethink your type hierarchy here.
Just remember the basic structure of inheritance. All SubFoo
s are Foo
s, but not all Foo
s are SubFoo
s.
Upvotes: 1