A function is always contravariant in its type of argument and covariant in its type of return value, for example,
trait Function1[-T1, +R] extends AnyRef trait Function2[-T1, -T2, +R] extends AnyRef
Here T1 , T2 , ..., T n (where n & lt; = 22 ) are arguments, and R is the return type .
In higher-order functions (functions that take a function as an argument), the argument may have a type parameter that is passed to the function, for example, foldLeft in the Iterable line
Iterable declared as
trait Iterable[+A] extends AnyRef
and foldLeft are marked as
def foldLeft[B](z : B)(op : (B, A) => B) : B
Since A declared covariant, it can be used as the return type. But there is instead an argument type due to
trait Function2[-T1, -T2, +R] extends AnyRef
because op : (B, A) => B is the literal type of Function2 .
The key to this is the Function2 trait is contravariant in argument type .
Consequently, the covariance type appears in the method argument due to
trait Function2 is contravariant in its type of argument
This is called a deviation :
- The reflection of covariance is a contravariance.
- The opposite is covariance.
- Flip invariant is an invariant.
Therefore, the invariant can appear in any position (covariance / contravariance)