# Type-oriented programming/Type variance

Consider the following type hierarchy:

```type A {}

type B : A {}

type F[T] {}
```

Without type arguments, `F` is a type operator while `F[A]` and `F[B]` are proper types. In general, neither is a subtype of the other. However it may sometimes make sense for them to be in a subtype relation depending on the hierarchy of their argument(s). If we declare `F` as follows

```type F[cov T] {}
```

then `F[B]` will be a subtype of `F[A]` because `B` is a subtype of `A`. Conversely, if we declare `F` as

```type F[con T] {}
```

then `F[A]` will be a subtype of `F[B]`. In the former case, we say that `F` is covariant in its type argument whereas in the latter case its contravariant (since the hierarchy is reversed).

A real-world example of type variance are function types. When we expect a function whose return type is `A` (that is, of type `Func[A]`), we can always use a function of type `Func[B]` in its stead. On the other hand, when we expect a function whose argument is of type `B` (that is, of type `Func[B,X]`, we can always use a function of type `Func[A,X]` in its stead. In sum, function types are covariant in their return type and contravariant in their arguments’ types.

NB: The pseudocode can be tried out using the Funcy app, which can be downloaded for free from Apple’s App Store (iOS/macOS), Google Play (Android) or Amazon Appstore. The code to be executed must be placed in a `main {}` block.