Here, "values", "types", and "kinds" have formal meanings, so considering their common English usage or analogies to classifying automobiles will only get you so far.
My answer pertains to the formal meanings of these terms in the context of Haskell specifically; these meanings are based on (though are not really identical to) the meanings used in mathematical/CS "type theory". So, this won't be a very good "computer science" answer, but it should serve as a pretty good Haskell answer.
In Haskell (and other languages), it ends up being helpful to assign a type to a program expression that describes the class of values the expression is permitted to have. I assume here that you've seen enough examples to understand why it would be useful to know that in the expression sqrt (a**2 + b**2)
, the variables a
and b
will always be values of type Double
and not, say, String
and Bool
respectively. Basically, having types assists us in writing expressions/programs that will work correctly over a wide range of values.
Now, something you may not have realized is that Haskell types, like those that appear in type signatures:
fmap :: Functor f => (a -> b) -> f a -> f b
are actually themselves written in a type-level Haskell sublanguage. The program text Functor f => (a -> b) -> f a -> f b
is -- quite literally -- a type expression written in this sublanguage. The sublanguage includes operators (e.g., ->
is a right associative infix operator in this language), variables (e.g., f
, a
, and b
), and "application" of one type expression to another (e.g., f a
is f
applied to a
).
Did I mention how it was helpful in many languages to assign types to program expressions to describe classes of expression values? Well, in this type-level sublanguage, expressions evaluate to types (rather than values) and it ends up being helpful to assign kinds to type expressions to describe the classes of types they are permitted to represent. Basically, having kinds assists us in writing type expressions that will work correctly over a wide range of types.
So, values are to types as types are to kinds, and types help us write value-level programs while kinds help us write type-level programs.
What do these kinds look like? Well, consider the type signature:
id :: a -> a
If the type expression a -> a
is to be valid, what kind of types should we permit variable a
to be? Well, the type expressions:
Int -> Int
Bool -> Bool
look valid, so the types Int
and Bool
are obviously of the right kind. But even more complicated types like:
[Double] -> [Double]
Maybe [(Double,Int)] -> Maybe [(Double,Int)]
look valid. In fact, since we ought to be able to call id
on functions, even:
(a -> a) -> (a -> a)
looks fine. So, Int
, Bool
, [Double]
, Maybe [(Double,Int)]
, and a -> a
all look like types of the right kind.
In other words, it looks like there's only one kind, let's call it *
like a Unix wildcard, and every type has the same kind *
, end of story.
Right?
Well, not quite. It turns out that Maybe
, all by itself, is just as valid a type expression as Maybe Int
(in much the same way sqrt
, all by itself, is just as valid a value expression as sqrt 25
). However, the following type expression is not valid:
Maybe -> Maybe
Because, while Maybe
is a type expression, it doesn't represent the kind of type that can have values. So, that's how we should define *
-- it's the kind of types that have values; it includes "complete" types like Double
or Maybe [(Double,Int)]
but excludes incomplete, valueless types like Either String
. For simplicity, I'll call these complete types of kind *
"concrete types", though this terminology isn't universal, and "concrete types" might mean something very different to, say, a C++ programmer.
Now, in the type expression a -> a
, as long as type a
has kind *
(the kind of concrete types), the result of the type expression a -> a
will also have kind *
(i.e., the kind of concrete types).
So, what kind of type is Maybe
? Well, Maybe
can be applied to a concrete type to yield another concrete type. So, Maybe
looks like a little like a type-level function that takes a type of kind *
and returns a type of kind *
. If we had a value level function that took a value of type Int
and returned a value of type Int
, we'd give it a type signature Int -> Int
, so by analogy we should give Maybe
a kind signature * -> *
. GHCi agrees:
> :kind Maybe
Maybe :: * -> *
Going back to:
fmap :: Functor f => (a -> b) -> f a -> f b
In this type signature, variable f
has kind * -> *
and variables a
and b
have kind *
; the built-in operator ->
has kind * -> * -> *
(it takes a type of kind *
on the left and one on the right and returns a type also of kind *
). From this and the rules of kind inference, you can deduce that a -> b
is a valid type with kind *
, f a
and f b
are also valid types with kind *
, and (a -> b) -> f a -> f b
is valid type of kind *
.
In other words, the compiler can "kind check" the type expression (a -> b) -> f a -> f b
to verify it's valid for type variables of the right kind the same way it "type checks" sqrt (a**2 + b**2)
to verify it's valid for variables of the right type.
The reason for using separate terms for "types" versus "kinds" (i.e., not talking about the "types of types") is mostly just to avoid confusion. The kinds above look very different from types and, at least at first, seem to behave quite differently. (For example, it takes some time to wrap your head around the idea that every "normal" type has the same kind *
and the kind of a -> b
is *
not * -> *
.)
Some of this is also historical. As GHC Haskell has evolved, the distinctions between values, types, and kinds have started to blur. These days, values can be "promoted" into types, and types and kinds are really the same thing. So, in modern Haskell, values both have types and ARE types (almost), and the kinds of types are just more types.
@user21820 asked for some additional explanation of "types and kinds are really the same thing". To be a little clearer, in modern GHC Haskell (since version 8.0.1, I think), types and kinds are treated uniformly in most of the compiler code. The compiler makes some effort in error messages to distinguish between "types" and "kinds", depending on whether it's complaining about the type of a value or the type of a type, respectively.
Also, if no extensions are enabled, they are easily distinguishable in the surface language. For example, types (of values) have a representation in the syntax (e.g., in type signatures), but kinds (of types) are -- I think -- completely implicit, and there's no explicit syntax where they appear.
But, if you turn on the appropriate extensions, the distinction between types and kinds largely disappears. For example:
{-# LANGUAGE GADTs, TypeInType #-}
data Foo where
Bar :: Bool -> * -> Foo
Here, Bar
is (both a value and) a type. As a type, its kind is Bool -> * -> Foo
, which is a type-level function that takes a type of kind Bool
(which is a type, but also a kind) and a type of kind *
and produces a type of kind Foo
. So:
type MyBar = Bar True Int
correctly kind-checks.
As @AndrejBauer explains in his answer, this failure to distinguish between types and kinds is unsafe -- having a type/kind *
whose type/kind is itself (which is the case in modern Haskell) leads to paradoxes. However, Haskell's type system is already full of paradoxes because of non-termination, so it's not considered a big deal.