0

Yes! Another of this question, and yes i already read alot of this questions in stackoverflow and still don't understand this concept and it's application.

So, i'm i new comer to Scala, and like many people i still didn't get the concept of Contravariance, i'm reading the Programming Scala, 2nd Edition, and on page 283 starts the explanation of co and contravariance with the following example:

gives the hierarchy:

class CSuper { def msuper() = println("CSuper") }
class C extends CSuper { def m() = println("C") }
class CSub extends C { def msub() = println("CSub") }

then there is a function and some examples of use:

var f: C => C = (c: C) => new C
    f         = (c: CSuper) => new CSub
    f         = (c: CSuper) => new C
    f         = (c: C) => new CSub
    f         = (c: CSub) => new CSuper // COMPILATION ERROR!

Thinking in java i know that the last expression won't compile because CSuper is a Supertype of CSub.

What i don't understand is what means a type, in this case the Function1[-C,+C], is contravariant in the first parameter?

The book says that for contravariance is when where X[String] is a supertype of X[Any], for some type X.

The co / contravariance is just appliable in the subclasses of the parameterized types, i mean since we are using a Function1, the variance just applies to subtypes of Function1, would be it?

And how does it actually works, and when should i use / need it?

Kennedy Oliveira
  • 2,141
  • 2
  • 20
  • 25
  • "i already read alot of this questions in stackoverflow and still don't understand..." — there isn't really any useful indication in your question of what we could possibly write that wouldn't just be the same as stuff you've already read. you've asked several questions here, all of them very broad, and all of them duplicates. – Seth Tisue Apr 06 '16 at 19:06
  • @SethTisue, yeah, i think the questions i already read has the knowledge i'm looking for, but, the way they are answered doesn't makes me understand, i was hoping someone could maybe explain in a different way. – Kennedy Oliveira Apr 06 '16 at 19:25
  • @KennedyOliveira Look for the Liskov Substitution Principle. – pedrofurla Apr 06 '16 at 19:41
  • @pedrofurla, thank you, i read about it long time ago, i forgot, read it again and sure helped me understand. – Kennedy Oliveira Apr 20 '16 at 15:08

1 Answers1

2

if T’ is a subclass of T, is Container[T’] considered a subclass of Container[T]?

[+T] covariant: C[T’] is a subclass of C[T],
[-T] contravariant: C[T] is a subclass of C[T’]

Function1 is defined as trait Function1[-T1, +R], so parameters are contravariant and result type is covariant.

That means, that functions, which arguments are supertypes of argument type of given function, and which result type is subtype of result type of given function is itself subtype of given function.

In your example, as you are assigning different function declarations to f of type C => C, only assigning of valid subtypes will compile.

Namely, only these function declarations are valid subtypes of C => C:

var f: C => C = (c: C) => new C
f         = (c: C) => new C
f         = (c: C) => new CSub
f         = (c: CSuper) => new C
f         = (c: CSuper) => new CSub

Everything else is either supertype of C => C and can't be assigned to f or unrelated type.

Aivean
  • 10,692
  • 25
  • 39