The typeclass Show
is declared as Show[T]
.
Contravariant
is declared as Contravariant[F[_]]
If we say that
Int
has kind *
List[Int]
has kind *
List
has kind * -> *
Monad
declared as trait Monad[M[_]]
has kind (* -> *) -> *
then by analogy:
Show
has kind * -> *
Show[Int]
has kind *
Contravariant
has kind (* -> *) -> *
Contravariant[Show]
has kind *
That is, Contravariant
is a thing that takes * -> *
and produces something of kind *
. Since Show
is of kind * -> *
, the type Contravariant[Show]
is valid.
Now, in your code snippet, there is an expression Contravariant[Show]
. It's not a type, and it should not be confused with the application of a type constructor. Desugared, this thing is essentially
Contravariant.apply[Show](inst)
where Contravariant
is the companion object of trait Contravariant
and inst
is an implicitly supplied instance of type Contravariant[Show]
. Again, everything fits together seamlessly.
Remark on nomenclature. I would say that Show
is a "higher kind". It's in no way definitive, but I like the following quote from the Atlassian Blog [emphasis and code indentation mine]:
Furthermore, you can have kinds that are themselves parameterized by higher kinded types. So, something could not only take a type, but take something that itself takes type parameters. An example would be the covariant functor: Functor[F[_]], it has the kind:
((* -> *) -> *)
This says: given a simple higher kinded type, produce the final type. For instance given a type constructor like List produce the final type Functor[List].
From the above quote it is evident that it is at least common to refer to the kind * -> *
of List
as "higher kind". It's definitely higher than *
. It's definitely higher than anything you can write down in current version of Java (if you write List
in Java, the best you can get is a "blah blah the generic type List requires type parameters blah blah"-error).