What’s the difference between parametric polymorphism and higher-kinded types?

Some terminology:

  • The kind * is sometimes called ground. You can think of it as 0th order.
  • Any kind of the form * -> * -> ... -> * with at least one arrow is first-order.
  • A higher-order kind is one that has a “nested arrow on the left”, e.g., (* -> *) -> *.

The order essentially is the depth of left-side nesting of arrows, e.g., (* -> *) -> * is second-order, ((* -> *) -> *) -> * is third-order, etc. (FWIW, the same notion applies to types themselves: a second-order function is one whose type has e.g. the form (A -> B) -> C.)

Types of non-ground kind (order > 0) are also called type constructors (and some literature only refers to types of ground kind as “types”). A higher-kinded type (constructor) is one whose kind is higher-order (order > 1).

Consequently, a higher-kinded type is one that takes an argument of non-ground kind. That would require type variables of non-ground kind, which are not supported in many languages. Examples in Haskell:

type Ground = Int
type FirstOrder a = Maybe a  -- a is ground
type SecondOrder c = c Int   -- c is a first-order constructor
type ThirdOrder c = c Maybe  -- c is second-order

The latter two are higher-kinded.

Likewise, higher-kinded polymorphism describes the presence of (parametrically) polymorphic values that abstract over types that are not ground. Again, few languages support that. Example:

f : forall c. c Int -> c Int  -- c is a constructor

The statement that Rust supports parametric polymorphism “instead” of higher-kinded types does not make sense. Both are different dimensions of parameterisation that complement each other. And when you combine both you have higher-kinded polymorphism.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)