I understand the terms co-variance and contra-variance. But there is one small thing I am unable to understand. In the course \"Functional Programming in Scala\" on coursera
I think the original question about converting Dog to Animal as already been clarified but it might be of interest to note that there is a reason why functions are defined contravariant in its arguments and covariant in its return types. Let’s say you have two functions:
val f: Vertebrate => Mammal = ???
val g: Mammal => Primate = ???
As we are talking about functions, you would expect functions composition to be amongst your primitive operations. Indeed, you can compose f and g (g o f) and obtain as result a function:
val h: Vertebrate => Primate = f andThen g
But I can replace g with a subtype:
val gChild: Animal => Primate
Without breaking the composability. And gChild is a subtype of g precisely because we defined Function contravariant in its argument. As a conclusion, you can see that a function must be defined in such a way if you want to capture and preserve the idea of functions composability.
You can find more details and few graphics that should help in digesting this subject here