We know that for two function types T1→T2 and S1→S2, T1→T2 ≤ S1→S2 iff S1≤T1 and T2≤S2 (ref). But I cannot come up with a realistic case where we want S1≤T1, as more likely we will use template/generic type to get around the Liskov substitution principle.
To facilitate the discussion, let's say we have the following classes (in Python)
class Animal: ...
class Cat(Animal): ...
class Habitat: ...
class Forest(Habitat): ...
on top of which we have "research center" classes, able to find the habitat for an animal. What won't work is
class AnimalResearchCenter:
def find_habitat(self, a: Animal) -> Habitat:
...
class CatResearchCenter(AnimalResearchCenter):
def find_habitat(self, c: Cat) -> Forest:
...
because the type of the argument of CatResearchCenter.find_habitat, Cat, should have been a supertype of Animal. In fact, mypy will complain
error: Argument 1 of "find_habitat" is incompatible with supertype "AnimalResearchCenter";
supertype defines the argument type as "Animal" [override]
note: This violates the Liskov substitution principle
and we should use Generic for this case:
from typing import Generic, TypeVar
T = TypeVar("T", bound=Animal)
class AnimalResearchCenter(Generic[T]):
def find_habitat(self, a: T) -> Habitat:
...
class CatResearchCenter(AnimalResearchCenter[Cat]):
def find_habitat(self, c: Cat) -> Forest:
...
So the question is, in what case we will want a method like find_habitat(self, a: Animal) -> Habitat in the base class?