Julio wrote:

> what does "contravariant" mean when contravariant functors are already obsolete?), precisely because of what you nicely explained in [#28](https://forum.azimuthproject.org/discussion/comment/19895/#Comment_19895), i.e. when we use the op-trick we should _not_ really still keep talking about "contravariant"!

Old fashioned terminology like *contravariant* still shows up in computer science.

Here is an example from the [Scala documentation](https://docs.scala-lang.org/tour/variances.html). Scala supports *subtyping* where we see the terminology come up.

Let's take a video game for example. In *Mario Brothers*, we can pretend the programmers created class \\(\mathtt{MarioEnemy}\\) for modeling enemies. That class has a subtype \\(\mathtt{Goomba}\\), and another subtype \\(\mathtt{KoopaTroopa}\\), with further subtypes \\(\mathtt{GreenKoopaTroopa}\\) and \\(\mathtt{RedKoopaTroopa}\\). The Subtypes form a little tree like this:

\[

\begin{matrix}

\mathtt{MarioEnemy} & \geq & \mathtt{Goomba} & & \\\\

& \geq & \mathtt{KoopaTroopa} & \geq & \mathtt{GreenKoopaTroopa} \\\\

& & & \geq & \mathtt{RedKoopaTroopa} \\\\

\end{matrix}

\]

So as you can see, subtyping in Scala forms a preorder.

A *parameterized class* like `Array[A]` or `Tuple[A,B]` is a type level constructor that takes a type as a parameter. These are like functors, but they do not need to be functors and are not more they are not.

A *covariant* class \\(\mathtt{F}\\) in Scala means that if there are two types \\(\mathtt{A} \leq \mathtt{B}\\) and then \\(\mathtt{F}\[\mathtt{A}\] \leq \mathtt{F}\[\mathtt{B}\]\\).

For instance, a list of \\(\mathtt{RedKoopaTroopa}\\) is a list of \\(\mathtt{KoopaTroopa}\\) because \\(\mathtt{List}\\) is *covariant*. In symbols:

\[\mathtt{RedKoopaTroopa} \leq \mathtt{KoopaTroopa} \Longrightarrow \mathtt{List}[\mathtt{RedKoopaTroopa}] \leq \mathtt{List}[\mathtt{KoopaTroopa}]\]

A *contravariant* class \\(\mathtt{G}\\) is one where \\(\mathtt{A} \leq \mathtt{B}\\) implies \\(\mathtt{G}\[\mathtt{B}\] \leq \mathtt{G}\[\mathtt{A}\]\\). These are more exotic, but a popular example is what Bartosz Milewski calls \\(\mathtt{Op}\\) (see [his 2015 blog post](https://bartoszmilewski.com/2015/02/03/functoriality/) on this). It's defined like this:

\[ \mathtt{Op}[+\mathtt{X}][-\mathtt{Y}] := \mathtt{Function}[\mathtt{Y},\mathtt{X}]\]

The class \\(\mathtt{Op}[\mathtt{X}]\\) is an example of a contravariant class: if \\(\mathtt{A}\leq \mathtt{B}\\) then \\(\mathtt{Op}\[\mathtt{X}\]\[\mathtt{B}\] \leq \mathtt{Op}\[\mathtt{X}\]\[\mathtt{A}\]\\).

To bring this back to category theory, old fashioned textbooks call \\(\mathtt{Op}\[\mathtt{X}\]\\) the [*contravariant Yoneda functor*](https://en.wikipedia.org/wiki/Yoneda_lemma#Naming_conventions).

I don't know if this helps...

> what does "contravariant" mean when contravariant functors are already obsolete?), precisely because of what you nicely explained in [#28](https://forum.azimuthproject.org/discussion/comment/19895/#Comment_19895), i.e. when we use the op-trick we should _not_ really still keep talking about "contravariant"!

Old fashioned terminology like *contravariant* still shows up in computer science.

Here is an example from the [Scala documentation](https://docs.scala-lang.org/tour/variances.html). Scala supports *subtyping* where we see the terminology come up.

Let's take a video game for example. In *Mario Brothers*, we can pretend the programmers created class \\(\mathtt{MarioEnemy}\\) for modeling enemies. That class has a subtype \\(\mathtt{Goomba}\\), and another subtype \\(\mathtt{KoopaTroopa}\\), with further subtypes \\(\mathtt{GreenKoopaTroopa}\\) and \\(\mathtt{RedKoopaTroopa}\\). The Subtypes form a little tree like this:

\[

\begin{matrix}

\mathtt{MarioEnemy} & \geq & \mathtt{Goomba} & & \\\\

& \geq & \mathtt{KoopaTroopa} & \geq & \mathtt{GreenKoopaTroopa} \\\\

& & & \geq & \mathtt{RedKoopaTroopa} \\\\

\end{matrix}

\]

So as you can see, subtyping in Scala forms a preorder.

A *parameterized class* like `Array[A]` or `Tuple[A,B]` is a type level constructor that takes a type as a parameter. These are like functors, but they do not need to be functors and are not more they are not.

A *covariant* class \\(\mathtt{F}\\) in Scala means that if there are two types \\(\mathtt{A} \leq \mathtt{B}\\) and then \\(\mathtt{F}\[\mathtt{A}\] \leq \mathtt{F}\[\mathtt{B}\]\\).

For instance, a list of \\(\mathtt{RedKoopaTroopa}\\) is a list of \\(\mathtt{KoopaTroopa}\\) because \\(\mathtt{List}\\) is *covariant*. In symbols:

\[\mathtt{RedKoopaTroopa} \leq \mathtt{KoopaTroopa} \Longrightarrow \mathtt{List}[\mathtt{RedKoopaTroopa}] \leq \mathtt{List}[\mathtt{KoopaTroopa}]\]

A *contravariant* class \\(\mathtt{G}\\) is one where \\(\mathtt{A} \leq \mathtt{B}\\) implies \\(\mathtt{G}\[\mathtt{B}\] \leq \mathtt{G}\[\mathtt{A}\]\\). These are more exotic, but a popular example is what Bartosz Milewski calls \\(\mathtt{Op}\\) (see [his 2015 blog post](https://bartoszmilewski.com/2015/02/03/functoriality/) on this). It's defined like this:

\[ \mathtt{Op}[+\mathtt{X}][-\mathtt{Y}] := \mathtt{Function}[\mathtt{Y},\mathtt{X}]\]

The class \\(\mathtt{Op}[\mathtt{X}]\\) is an example of a contravariant class: if \\(\mathtt{A}\leq \mathtt{B}\\) then \\(\mathtt{Op}\[\mathtt{X}\]\[\mathtt{B}\] \leq \mathtt{Op}\[\mathtt{X}\]\[\mathtt{A}\]\\).

To bring this back to category theory, old fashioned textbooks call \\(\mathtt{Op}\[\mathtt{X}\]\\) the [*contravariant Yoneda functor*](https://en.wikipedia.org/wiki/Yoneda_lemma#Naming_conventions).

I don't know if this helps...