Search code examples
scalatype-systems

covariance and variance flip in scala


In Scala for the Impatient It is said that

functions are contra-variant in their arguments and covariant in their result type

This is straightforward and easy to understand ,however in the same topic it says

However inside a function parameter ,the variance flips- its parameters are covariant

and it takes the example of foldLeft method of Iterator as :

 def foldLeft[B](z : B)(op : (B, A) => B) : B 

I am not getting it clearly what it says.

I tried some of blogs as

  1. http://www.artima.com/pins1ed/type-parameterization.html

  2. http://blog.kamkor.me/Covariance-And-Contravariance-In-Scala/

  3. http://blogs.atlassian.com/2013/01/covariance-and-contravariance-in-scala/

But didn't get clear understanding.


Solution

  • A function is always contravariant in its argument type and covariant in its return type e.g.

    trait Function1[-T1, +R] extends AnyRef 
    
    trait Function2[-T1, -T2, +R] extends AnyRef 
    

    Here, T1,T2, ..., Tn (where n <= 22) are arguments and R is the return type.

    In higher order functions (functions that take function as argument), an argument can have the type parameter that is passed into the function e.g. foldLeft in trait Iterable

    Iterable is declared as

    trait Iterable[+A] extends AnyRef
    

    and foldLeft is decalred as

    def foldLeft[B](z : B)(op : (B, A) => B) : B 
    

    Since A is declared covariant, it can be used as the return type. But here it 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 trait Function2 is contravariant in its argument type.

    Hence covariance type is appearing in method argument due to

    trait Function2 is contravariant in its argument type

    This is called variance flip:

    1. Flip of covariance is contravariance.
    2. Flip of contravariance is covariance.
    3. Flip is invariant is invariant.

    That's why invariant may appear at any position (covariance/contravariance)