Your class can be viewed as
trait Function1[-Input, +Result] // Renamed the type parameters for clarity
case class Foo[+A](a: A) {
val bar: Function1[A, A] = identity
val zar: Function1[Function1[A, Int], Int] = { f => f(a) }
}
The approach taken by the compiler is to assign positive, negative, and neutral annotations at each type position in the signature; I'll notate the positions by putting + and - after the type in that position
First the top-level vals are positive (i.e. covariant):
case class Foo[+A](a: A) {
val bar: Function1[A, A]+
val zar: Function1[Function1[A, Int], Int]+
}
bar can be anything that's a subtype of Function1[A, A] and zar can be anything that's a subtype of Function1[Function1[A, Int], Int], so this makes sense (LSP, etc.).
The compiler then moves into the type arguments.
case class Foo[+A](a: A) {
val bar: Function1[A-, A+]
val zar: Function1[Function1[A, Int]-, Int+]
}
Since Input is contravariant, this "flips" the classification (+ -> -, - -> +, neutral unchanged) relative to its surrounding classification. Result being covariant does not flip the classification (if there was an invariant parameter in Function1, that would force the classification to neutral). Applying this a second time
case class Foo[+A](a: A) {
val bar: Function1[A-, A+]
val zar: Function1[Function1[A+, Int-], Int+]
}
A type parameter for the class being defined can only be used in + position if it's covariant, - position if contravariant, and anywhere if it's invariant (Int, which is not a type parameter can be considered invariant for the purpose of this analysis: i.e. we could have dispensed with annotating once we got to a type which neither was a type parameter nor had a type parameter). In bar, we have a conflict (the A-), but in zar the A+ means no conflict.
The produce/consume relationship presented in Luis's answer is a good intuitive summary. This is a partial (methods with type parameters complicate this, though I'm not totally sure how my transformation would work there...) exploration of how the compiler actually concludes that the A in zar is in a covariant position; Programming in Scala (Odersky, Spoon, Venners) describes it in more detail (in the 3rd edition, it's in section 19.4).