Senger CodeLab 🚀

What is a higher kinded type in Scala

September 29, 2026

What is a higher kinded type in Scala

Scala, a powerful language blending object-oriented and functional paradigms, offers a unique feature known as higher-kinded types. This concept, while initially appearing complex, unlocks significant power and flexibility in your code. Understanding higher-kinded types is crucial for leveraging Scala’s type system to its fullest and writing truly reusable, abstract code. This post will demystify higher-kinded types, explaining what they are, why they’re important, and how to use them effectively in your Scala projects.

What are Higher-Kinded Types?

In essence, a higher-kinded type is a type that takes other types as parameters. Think of it as a type constructor, similar to a function that takes arguments but instead of returning a value, it returns a new type. This allows for a level of abstraction not possible with regular types, enabling you to write generic code that works across a wide range of data structures and operations.

For example, consider the concept of a “container” like List or Option. These types aren’t complete on their own; they need a type parameter to specify what they contain – a List[Int], an Option[String], and so on. Higher-kinded types allow you to abstract over these container types themselves, writing code that operates on any “container” regardless of the specific type it holds.

This is powerful because it promotes code reuse and reduces boilerplate. You can write algorithms once and apply them to various contexts without modification, making your code more concise and maintainable.

Why Use Higher-Kinded Types?

Higher-kinded types are essential for building type-safe abstractions in Scala. They allow you to express relationships between types and enforce those relationships at compile time, preventing errors and improving code reliability. This capability becomes particularly important when working with complex data structures and operations.

One compelling use case is building generic functions that operate on different kinds of containers. Imagine writing a function that maps over a collection, applying a transformation to each element. With higher-kinded types, you can write this function once and use it with lists, options, futures, and other container types without rewriting it for each specific case.

Furthermore, higher-kinded types facilitate the creation of type classes, a powerful mechanism for ad-hoc polymorphism. Type classes allow you to define behavior for types without modifying the types themselves, enabling a more modular and extensible code design.

How to Use Higher-Kinded Types in Scala

Defining a higher-kinded type in Scala involves using a type parameter placeholder within square brackets, prefixed with a type parameter name. For instance, trait Functor[F[_]] defines a higher-kinded type F that takes one type parameter.

Here’s a simplified example demonstrating how to define and use a higher-kinded type for a Functor:

scala trait Functor[F[_]] { def map[A, B](fa: F[A])(f: A => B): F[B] } // Example implementation for List implicit val listFunctor: Functor[List] = new Functor[List] { override def map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f) } // Usage val list = List(1, 2, 3) val doubledList = listFunctor.map(list)(_ 2) // List(2, 4, 6) This example illustrates how a higher-kinded type F[_] is used to abstract over the List type. The map function can then operate on any type for which a Functor instance is defined.

Advanced Applications of Higher-Kinded Types

Beyond basic functors, higher-kinded types are instrumental in advanced functional programming concepts like monads, applicative functors, and traversables. These abstractions enable sophisticated operations on nested data structures, error handling, and asynchronous programming in a type-safe and composable manner.

Libraries like Cats and Scalaz leverage higher-kinded types extensively to provide powerful abstractions for functional programming in Scala. Understanding higher-kinded types is crucial for effectively utilizing these libraries and taking full advantage of Scala’s functional capabilities.

For example, consider working with a nested data structure like List[Option[Int]]. Using a monad like List along with a higher-kinded type allows you to flatten this structure efficiently and elegantly, a task that would be significantly more complex without higher-kinded types. This is just a glimpse of the power that higher-kinded types offer.

  • Enables code reuse and reduces boilerplate.
  • Facilitates the creation of type classes for ad-hoc polymorphism.
  1. Define the higher-kinded type using a type parameter placeholder.
  2. Implement the type class for specific types.
  3. Use the type class to operate on values of those types.

Infographic Placeholder: Visual representation of higher-kinded types and their relationship with other types.

Learn More about ScalaAs we’ve seen, higher-kinded types are a powerful tool for abstracting over types and building reusable code. While they may seem daunting at first, understanding their core principles unlocks a new level of expressiveness in your Scala code. By leveraging higher-kinded types, you can write more concise, maintainable, and type-safe programs. Explore further and discover how higher-kinded types can elevate your Scala programming to the next level.

Explore related topics such as type classes, monads, and functional programming in Scala to deepen your understanding and further refine your skills.

Scala Official Website
Cats Library
Scalaz Library
Frequently Asked Questions

Q: Are higher-kinded types unique to Scala?

A: While prominently featured in Scala, the concept of higher-kinded types exists in other languages like Haskell and OCaml as well.

Q: What’s the difference between a type parameter and a higher-kinded type?

A: A type parameter allows you to specify a concrete type when using a class or function. A higher-kinded type takes types as parameters, allowing you to abstract over type constructors like List or Option.

Question & Answer :
You can find the following on the web:

  1. Higher kinded type == type constructor?

    class AClass[T]{...} // For example, class List[T] 
    

    Some say this is a higher kinded type, because it abstracts over types which would be compliant with the definition.

    Higher kinded types are types which take other types and construct a new type

    These though are also known as type constructor. (For example, in Programming in Scala).

  2. Higher kinded type == type constructor which takes type constructor as a type parameter?

    In the paper Generics of a Higher Kind, you can read

    … types that abstract over types that abstract over types (‘higher-kinded types’) …"

    which suggests that

    class XClass[M[T]]{...} // or trait YTrait[N[_]]{...} // e.g. trait Functor[F[_]] 
    

    is a higher kinded type.

So with this in mind, it is difficult to distinguish between type constructor, higher kinded type and type constructor which takes type constructors as type parameter, therefore the question above.

Let me make up for starting some of this confusion by pitching in with some disambiguation. I like to use the analogy to the value level to explain this, as people tend to be more familiar with it.

A type constructor is a type that you can apply to type arguments to “construct” a type.

A value constructor is a value that you can apply to value arguments to “construct” a value.

Value constructors are usually called “functions” or “methods”. These “constructors” are also said to be “polymorphic” (because they can be used to construct “stuff” of varying “shape”), or “abstractions” (since they abstract over what varies between different polymorphic instantiations).

In the context of abstraction/polymorphism, first-order refers to “single use” of abstraction: you abstract over a type once, but that type itself cannot abstract over anything. Java 5 generics are first-order.

The first-order interpretation of the above characterizations of abstractions are:

A type constructor is a type that you can apply to proper type arguments to “construct” a proper type.

A value constructor is a value that you can apply to proper value arguments to “construct” a proper value.

To emphasize there’s no abstraction involved (I guess you could call this “zero-order”, but I have not seen this used anywhere), such as the value 1 or the type String, we usually say something is a “proper” value or type.

A proper value is “immediately usable” in the sense that it is not waiting for arguments (it does not abstract over them). Think of them as values that you can easily print/inspect (serializing a function is cheating!).

A proper type is a type that classifies values (including value constructors), type constructors do not classify any values (they first need to be applied to the right type arguments to yield a proper type). To instantiate a type, it’s necessary (but not sufficient) that it be a proper type. (It might be an abstract class, or a class that you don’t have access to.)

“Higher-order” is simply a generic term that means repeated use of polymorphism/abstraction. It means the same thing for polymorphic types and values. Concretely, a higher-order abstraction abstracts over something that abstracts over something. For types, the term “higher-kinded” is a special-purpose version of the more general “higher-order”.

Thus, the higher-order version of our characterization becomes:

A type constructor is a type that you can apply to type arguments (proper types or type constructors) to “construct” a proper type (constructor).

A value constructor is a value that you can apply to value arguments (proper values or value constructors) to “construct” a proper value (constructor).

Thus, “higher-order” simply means that when you say “abstracting over X”, you really mean it! The X that is abstracted over does not lose its own “abstraction rights”: it can abstract all it wants. (By the way, I use the verb “abstract” here to mean: to leave out something that is not essential for the definition of a value or type, so that it can be varied/provided by the user of the abstraction as an argument.)

Here are some examples (inspired by Lutz’s questions by email) of proper, first-order and higher-order values and types:

proper first-order higher-order values 10 (x: Int) => x (f: (Int => Int)) => f(10) types (classes) String List Functor types String ({type λ[x] = x})#λ ({type λ[F[x]] = F[String]})#λ 

Where the used classes were defined as:

class String class List[T] class Functor[F[_]] 

To avoid the indirection through defining classes, you need to somehow express anonymous type functions, which are not expressible directly in Scala, but you can use structural types without too much syntactic overhead (the #λ-style is due to https://stackoverflow.com/users/160378/retronym afaik):

In some hypothetical future version of Scala that supports anonymous type functions, you could shorten that last line from the examples to:

types (informally) String [x] => x [F[x]] => F[String]) // I repeat, this is not valid Scala, and might never be 

(On a personal note, I regret ever having talked about “higher-kinded types”, they’re just types after all! When you absolutely need to disambiguate, I suggest saying things like “type constructor parameter”, “type constructor member”, or “type constructor alias”, to emphasize that you’re not talking about just proper types.)

ps: To complicate matters further, “polymorphic” is ambiguous in a different way, since a polymorphic type sometimes means a universally quantified type, such as Forall T, T => T, which is a proper type, since it classifies polymorphic values (in Scala, this value can be written as the structural type {def apply[T](x: T): T = x})