Functors in Scala
05 Feb 2017Scala’s type is very rich; even where constructs aren’t well defined you can easily piece together anything that you need. In today’s article, I’ll take you through some different functor types as well as a small primer on variance.
Variance
Type variance is what we use to describe sub-class relationships in a class hierarchy. In scala we use the following notations to denote variances:
| Description | Notation | |
|---|---|---|
| covariant | C[T'] is a subclass of C[T] |
[+T] |
| contravariant | C[T] is a subclass of C[T'] |
[-T] |
| invariant | C[T] and C[T'] are not related |
[T] |
Functors
Covariant functors are what provide map or fmap:
trait Functor[F[_]] {
def fmap[A, B](f: A => B): F[A] => F[B]
}Contravariant functors provide contramap:
trait Contravariant[F[_]] {
def contramap[A, B](f: B => A): F[A] => F[B]
}Exponential functors are what provide xmap:
trait Exponential[F[_]] {
def xmap[A, B](f: (A => B, B => A)): F[A] => F[B]
}Applicative functors are what provide apply and <*>:
trait Applicative[F[_]] {
def apply[A, B](f: F[A => B]): F[A] => F[B]
}Monads provide bind, flatMap or =<<:
trait Monad[F[_]] {
def flatMap[A, B](f: A => F[B]): F[A] => F[B]
}Comonads provide extend, coflatMap and <<=:
trait Comonad[F[_]] {
def coflatMap[A, B](f: F[A] => B): F[A] => F[B]
}