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 betweenAandB. The fact thatListis covariant inAjust means thatList[B] <: List[A]whenB <: A, as you know already know.On the other hand,
Listexposes a methodmapto change its "contents". This method does not really care aboutList[A], but only aboutAs, so the variance ofListis irrelevant here. The bit that is confusing you here is that there is indeed some sub-typing to take into consideration:mapaccepts an argument (aA => Cin 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, anyAcceptedTypewill be ok, as long asAcceptedType <: Function1[A,C]. The variance that matters here isFunction's, notList's.