6

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?

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
Tom
  • 5,848
  • 12
  • 44
  • 104
  • 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. m. could be an AI Aug 27 '17 at 06:22
  • 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 Aug 27 '17 at 07:39
  • If it weren't higher kinded than what would the signature of `map` look like? – sepp2k Aug 27 '17 at 07:41
  • `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. m. could be an AI Aug 27 '17 at 07:45

2 Answers2

8

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?

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
1

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.

Haspemulator
  • 11,050
  • 9
  • 49
  • 76