Chapter 11: What are Kinds in Scala?

Kinds?

In chapter 1 we discussed values and with the help of Types we categories our values. We can say that Types are abstractions of values or in simple terms one-level above from values. Similarly, we have Kinds, Kinds are the abstraction of Types or we can say that, another level of values as you can see in the below diagram.

Now the question is, how can we figure out what is the Kind of any type? This is really the trickiest question, while we are creating any generics class or trait we define some abstract characters like A, T, and more, as we defined in chapter 6. If we want to check the Kind of any Type, below is the Scala REPL command.

scala> :k String
String's kind is A

scala> :k Int
String's kind is A

In Scala REPL we can use :k or :kind to describe the Kind of any type.

In the first example, the output of String is A, A is similar to invariant as we defined in chapter 10 and it could be any Type. In the second example, we have the same output, because A could be any type, that's why Kinds are a more abstract version of Types.

Let’s take some other detailed examples.

scala> :k -v String
String's kind is A
*
This is a proper type.

In this example, we are using the additional flag -v which denotes to verbose mode output, or we can say that details output. In this detailed output, we are one special character * (asterisk).

Note: * (asterisk) symbol is only used by the compiler for explaining the types, we can't directly use * (asterisk) for type abstraction.

In Type-System * (asterisk) is the symbol that denotes to define types and its structure like String is the concrete type without any parameter, so it denotes via single * (asterisk). Let’s take some complex type as below:

scala> :k -v List
List's kind is F[+A]
* -(+)-> *
This is a type constructor: a 1st-order-kinded type.

In this example, List is a parameterized constructor with co-variant types, in this case Kind of List type defined by the symbolic way as * -(+)-> * . As we know * (asterisk) denotes to types and (+) denotes co-variance, so we can say that List[+T] or F[+A] symbolic Kind value is * -(+)-> *.

Note: To understand symbolic representation of Kinds, evaluate from Left to Right. This is for our understanding but I am not sure about the compiler evaluation.

Let's explore some more example:

scala> :k -v Map
Map's kind is F[A1,+A2]
* -> * -(+)-> *
This is a type constructor: a 1st-order-kinded type.

scala> :k -v Either
Either's kind is F[+A1,+A2]
* -(+)-> * -(+)-> *
This is a type constructor: a 1st-order-kinded type.

In the case of multiple parameters type constructor like Map or Either, the Kind symbols are slightly different. The first * (asterisk) or left * (asterisk) denotes the outer type as we know like Map or Either and but the right side of them define the inner types like in the case of Map key is invariant and value is co-variance so our output is * -> * -(+)-> * and in the case of Either both are co-variance our output is * -(+)-> * -(+)-> *. On the basis of invariant or co-variant, the variance with symbols are decided.

These are the basics of Kinds and in the next chapter, we will explore Higher Kinded Types with example.

Last updated