### 1. Overview

On this tutorial, we’ll check out *Functor* kind class in *Cats*. The concept of *Functor* is “one thing that may be mapped over”, we’ll see what is definitely mapped and the way. In practical programming, ** Functors come into play when we now have varieties or values wrapped inside contexts or containers.** We don’t need to know any of the implementation particulars of these contexts or containers themselves.

### 2. SBT Dependencies

To start out, let’s add the Cats library to our dependencies :

libraryDependencies += "org.typelevel" %% "cats-core" % "2.2.0"

Right here we’re utilizing model 2.2.0 of the Cats library.

### 3. What’s a Functor?

When it comes to practical programming, **a Functor is a type of container that may be mapped over by a perform. **It’s mainly an abstraction that enables us to jot down generic code that can be utilized for

*Futures*,

*Choices*,

*Lists*,

*Both*, or every other mappable kind.

In easy phrases, **any kind that has a map perform outlined and ideally an “identification perform” is a Functor.**

Customary library has no native base trait/kind to characterize this so we are able to write :

def calcBudget(orders: Record[LineItem]) = orders.map(...) def calcBudget(maybeOrder: Choice[LineItem]) = maybeOrder.map(...) def calcBudget(eventualOrder: Future[LineItem]) = eventualOrder.map(...)

However we are able to’t write it generically like this :

def calcBudget(order: Functor[LineItem]) = order.map(...)

### 4. The Cats Functor Sort Class

Nevertheless utilizing cats’ *Functor *kind class we are able to write a generic code that can be utilized for *Futures*, *Choices*, *Lists*, *Both*, or every other mappable kind.

However earlier than that, let see definition of *Functor* kind class. A *Functor *is outlined as *F[A]* with a map operation *(A => B) => F[B]* :

bundle cats trait Functor[F[_]] def map[A, B](fa: F[A])(f: A => B): F[B]

Now let’s rewrite *calcBudget *utilizing *Functor *:

import cats.Functor case class LineItem(worth: Double) def calcBudget[F[_]](order: F[LineItem])(implicit functorEvidence: Functor[F]): F[LineItem] = Functor[F].map(order)(o => o.copy(worth = o.worth * 1.2))

Let’s decode this technique signature.

The *calcBudget* technique is parameterized primarily based on a sort of *F[_]*. Right here *F[_]* means any mappable kind e.g. *Choice*, *Record*, *Future*, and so forth. The parameter *order* itself is of kind *F[LineItem]* i.e. any kind wrapping a *LineItem*.

The implicit parameter *functorEvidence: Functor[F]* signifies that we should have a *kind class implementation,* which permits us to deal with *F* as a *Functor*.

In technique physique, we name *Functor[F].map()* i.e. we create a Functor for *F* utilizing implicit proof *functorEvidence* and name it’s *map* technique.

### 5. Functor Legal guidelines

If we’re creating our personal *Functors*, then these *Functors *need to respect some guidelines, known as *Functor’s Legal guidelines* :

### 5.1. Id Regulation

When a *Functor* is mapped over with identification perform (the perform returning its parameter unchanged), then we should get again the unique *Functor *(the container and its content material stay unchanged).

Functor[X].map(x => identification(x)) == Functor[X]

### 5.2. Composition Regulation

When a *Functor *mapped over the composition of two capabilities, then it ought to be identical as mapping over one perform after the opposite one.

Functor[X].map(f).map(g) == Functor[X].map(x => g(f(x))

### 6. Examples of Functors in Scala

In Scala, we’re conscious of *Functor’s* *map *perform to work with results. **Cats present varied kind class implementations for Functors**, for predefined varieties like

*Lists*,

*Futures*,

*Choices*,

*Both*, and so forth.

### 6.1. Record as a Functor

Now, let’s see how *Record* act as a *Functor* :

*Record* is taken into account as a *Functor* because it has a *map* technique. Whereas iterating over *Record* utilizing its *map* technique, we must always consider it as remodeling the entire values inside in a single go, with out altering the construction of the *Record*.

We are able to implement the above idea utilizing following instance :

import cats.Functor object ListFunctor def transformList(checklist: Record[Int]): Record[Int] = Functor[List].map(checklist)(_ * 2) val checklist: Record[Int] = Record(1, 2, 3, 4, 5) val transformedList = Record(2, 4, 6, 8, 10) assert(ListFunctor.transformList(checklist) == transformedList)

### 6.2. Choice as a Functor

Now, let’s see how *Choice* act as a *Functor* :

*Choice *can also be thought of as a *Functor* because it additionally has a *map* technique. Once we map over an *Choice*, we rework the contents however depart the *Some* or *None* context unchanged.

We are able to implement the above idea utilizing following instance :

import cats.Functor object OptionFunctor def transformOption(choice: Choice[Int]): Choice[String] = Functor[Option].map(choice)(_.toString) val choice: Choice[Int] = Some(10) val transformedOption = Some("10") assert(OptionFunctor.transformOption(choice) == transformedOption)

### 6.3. Both as a Functor

Now, let’s see how *Both *act as a *Functor* :

*Both *can also be thought of as a *Functor* because it additionally has a *map* technique. Once we map over an *Both*, we rework the contents however depart the *Left *or *Proper *context unchanged.

We are able to implement the above idea utilizing following instance :

import cats.Functor object EitherFunctor def transformEither(both: Both[Int, String]): Both[Int, Int] = Functor[Either].left.map(both)(_.measurement) val both: Both[Int, String] = Left("Baeldung") val transformedEither = Left(8) assert(EitherFunctor.transformedEither(both) == transformedEither)

### 6.4. Future as a Functor

Now, let’s see how *Future *act as a *Functor* :

*Future* is a *Functor* that sequences asynchronous computations by queueing them and making use of them as their predecessors full. The kind signature of its *map* technique has the identical form because the signatures above. Nevertheless, the habits may be very totally different. **In case of Future, the wrapped computation could also be ongoing, full, or rejected.** If the

*Future*is full, our mapping perform may be known as instantly. If not, some underlying thread pool queues the perform name and comes again to it later. We don’t know when our capabilities might be known as, however we do know what order they are going to be known as in. On this means,

**.**

*Future*gives the identical sequencing habits seen in*Record*,*Choice*, and*Both*We are able to implement the above idea utilizing following instance :

import cats.Functor object FutureFunctor def transformFuture(future: Future[Int]): Future[Int] = Functor[Future].map(future)(_ + 1) val future: Future[Int] = Future10 val transformedFutureResult = 11 FutureFunctor.transformFuture(future).map(consequence => assert(consequence == transformedFutureResult))

### 7. Significance of Functors

By utilizing Functors we’re not restricted to the categories in the usual library, thus we are able to summary over something that’s mappable.** We may outline a map technique to our personal varieties **through the use of the idea of *syntax* or *extension* strategies. This idea permits us to jot down *order.map(…)* as a substitute of *Functor[F].map(order)(…)*. We are able to additionally drop the implicit proof parameter by specifying that kind *F[_]* is a *Functor *:

import cats.syntax.functor._ //for map def calcBudget[F[_]: Functor](order: F[LineItem]): F[LineItem] = order.map(o => o.copy(worth = o.worth * 1.2))

However we are able to additionally construct a higher-order perform that may take care of any kind and carry out any mapping operation :

def withFunctor[A, B, F[_]](merchandise: F[A], op: A => B)(implicit functorEvidence: Functor[F]): F[_] = Functor[F].map(merchandise)(op) val lineItemsList = Record(LineItem(10.0), LineItem(20.0)) val consequence = FunctorSyntax.withFunctor(lineItemsList, calcBudget) assert(consequence == Record(LineItem(10.0), LineItem(20.0)))

In above instance, *A*, *B* & *F* may be something as long as the caller of the tactic :

- Provides proof that
*F*is a*Functor* - Is aware of how you can map from
*A*to*B*

### 8. Abstract

On this article, we’ve checked out *Functors* offered by Cats library of Scala. *Functor *is a type of container that gives mapping perform to characterize sequencing behaviors. We talked about what’s the want of *Functors* and the way can we outline them. Then we discovered about two legal guidelines {that a} *Functor* has to respect. Then we noticed that we are able to write *Functor *kind class implementation for all of the *mappable *varieties current in Scala ecosystem *like* *Futures*, *Choices*, *Lists, Both, *and so forth. We’re not restricted to the categories in the usual library. We are able to additionally outline *map* technique to our personal varieties through the use of the idea of *syntax *or *extension* strategies.

All of the code implementations can be found over on GitHub.

Supply hyperlink