I have a question that's been bugging me.
Lists in Scala are covariant (List[+A]
)
Let's say we have these classes:
class A
class B extends A
The map
function of List[B]
takes a function f: B => C
But I can also use a f: A => C
which is a subclass of f: B => C
and it totally makes sense.
What I am currently confused by is that
the map
function should accept only functions that are superclasses of the original function (since functions are contravariant on their arguments), which does not apply in the example I've given.
I know there's something wrong with my logic and I would like to enlightened.
As you already suspected, you are mixing up things here.
On the one hand, you have a
List[+A]
, which tells us something about the relationships betweenList[A]
andList[B]
, given a relationship betweenA
andB
. The fact thatList
is covariant inA
just means thatList[B] <: List[A]
whenB <: A
, as you know already know.On the other hand,
List
exposes a methodmap
to change its "contents". This method does not really care aboutList[A]
, but only aboutA
s, so the variance ofList
is irrelevant here. The bit that is confusing you here is that there is indeed some sub-typing to take into consideration:map
accepts an argument (aA => C
in this case, but it's not really relevant) and, as usual with methods and functions, you can always substitute its argument with anything that is a subtype of it. In your specific case, anyAcceptedType
will be ok, as long asAcceptedType <: Function1[A,C]
. The variance that matters here isFunction
's, notList
's.