5
votes

I have following functor definition

trait Functor[F[_]] { 
    def map[A, B](fa: F[A])(f: A => B): F[B]
}
object ListFunctor extends Functor[List] { //
    def map[A, B](f: A => B)(data: List[A]): List[B] = data map f
}

In scala, it is very common that F is a collection type, such as List,Seq,Option, I would ask why Functor has to be higher kinded type, and what does the type parameter F really mean?

2
Functor is a common interface for many (higher kinded) types like List and Option. The type parameter F says "this is the type we define our interface for".n. 1.8e9-where's-my-share m.
Thanks @n.m. Your explanation makes sense from the code's view. I want to ask why functor takes form such as Functor[F[_]]. It looks to me that functor is aiming to transform F[A] to F[B] given A=>B, F's meaning here doesn't really matter. It can be a container or context or some others, as long as F[A] and F[B] is meaningful.Tom
If it weren't higher kinded than what would the signature of map look like?sepp2k
Functor[F[_]] looks like that because we want to use Functor[List] and Functor[Option] and Functor[Stream] and others like that. List, Option and Stream are all higher-kinded types that have exactly one type parameter. F[_] is a way to express this last fact. _ is a placeholder for the type parameter of F.n. 1.8e9-where's-my-share m.

2 Answers

7
votes

why Functor has to be higher kinded type

Functor has to be higher kinded because we want to abstract over a type parameter which itself takes a type parameter (we call this a type constructor, think Functor[List] as a concrete example).

The type of types that Functor deals with are called "first order kinds", their kind is of * -> *. When you looking at concrete instances for Functor, you see we dont provide the inner type parameter. For example, when you define a functor for List as you did in your example, you define it as a Functor[List]. We're not creating a functor for a proper type (i.e. List[Int]), but rather any type contained inside the List. This abstraction brings great power, because you can utilize it for any proper List type (of kind *), be it List[String], List[Int], etc..

I always like to refer to the image drawn by Adriaan Moore in his paper "Genrics Of A Higher Kind":

Higher Kinds

What does the type parameter F really mean

Fs sole purpose is to define a contract with the implementer of the Functor. By the signature of F we can deduce what kind of type Functor expects. When we see that it has one "placeholder" ([_]) we know, by convention, that this means that F should take a single type parameter. If we think about all the types that take a single type parameter, we can see that there are many, for example List, Option, Try, Future, Task, etc.

For a more broad explanation regarding higher kinded types, see What is a higher kinded type in Scala?

0
votes

I'd answer this a bit differently. The presence of a (higher-kinded) type parameter F[_] in Functor signature means Functor is a typeclass. Typeclasses is a Scala feature that allows one to add features to existing types without modifying them. So Functor[F[_]] here is not a single type, but a blueprint for many other types. Or, in other words, it is not a single type, but a class of types, hence the word "typeclass".

Now to create a concrete functor, e.g. functor of list, one needs to pass that concrete type as a type parameter to that blueprint, and that concrete type itself has to have one type parameter, by mathematical definition of functor, if you wish. This is what higher-kinded type F[_] in Functor signature means.