In functional programming, we have various pillars like **Functors**, **Monads**, **Applicative** and more. Today we will try to explore one of these pillars called **Functors**. First let’s explore function composition:

**Function Composition: **

- In this diagram, we have
**3 sets**called**A**,**B**, and**C**. - Set
**A**contains an element called**x**. - Suppose, we need to convert our
**Set A**elements into**Set C**. But we have no direct path with**Set C.****Set B**is behaving as an intermediator in this case.- First, we need to compose a function
**f**which converts elements**x**into result**f(x)**. - Now, we can see that
**Set B**has element**f ( x )**, so we need to compose another function**g**which converts**f ( x )**into**g ( f ( x ) )**. - By using
**g ( f ( x ) ),**we have successfully converted elements of**Set A**into**Set C**.

- First, we need to compose a function

According to above example, we are creating **g ( f ( x ) )** for our results, which is actually called function composition. Let’s take a scala example:

val f = ( x: Int ) => x.String

val g = ( fx: String ) => Symbol( fx )

We are creating two methods. Our requirements are that we need to convert an integer value into the symbol. Let’s suppose that we don’t have any direct way for this conversion. But we have two functions, which will help us to achieve our goal. First, function** f** which converts **Int => String** and second, function **g**, which converts **String => Symbol**. In that case, we would start composing function like below:

val result = g ( f( x ) )

**OR**

val result = ( f andThen g )( 8 )

This is called **function composition**. By using **scala-cats**, we can compose the functions with **map** method, which we will be discussing later.

Now, let’s try to figure out about functors.

**Functors: **

According to the diagram, we have two sets **C** and **D**. But in the case of functors, things are a little bit different.

- In the diagram, we have the following components :
**(a, b)**are elements,**F**is functor and**f**is a function. - The set
**D**is a kind of mirror of set**C**or we can say,**D**is used to lift the elements of**C**with the functors wrapping. - In functor, the compositions of elements are done within the same set and another set is used as a mirror or a lift for wrapping the elements into functors.
- Rather than composing a function on
**set C**element to**set D**, we actually lift the elements or in the layman term, by using functors**( F ),**we are wrapping the elements into another**set**. - The types of elements are independent.
**Functors**can wrap any type of elements. - In the same set, if an element
**a**is converted into element**b**as**(a => b)**with the help of some mapping called**f,**then in the mirror set, same things will happen, i.e. element**Fa => Fb**is converted by using**Ff**mapping. - In the functors, the method composition is executed in a sequential order.
- In the functors, the structure is always same. For example, while converting
**Fa => Fb**, type of**F**will always be the same.

Now let’s take a look at some **scala** examples.

In this diagram, we have a functor called **Option**. If we wrap or lift the element **A** and **B** with functors(like in the above diagram), we are getting **Option[A]** and **Option****[B]**. As we know, we have mapping method between **A => B** called **f** and if we lift the **f** using functors, in Scala we get an **Option **of** f** which is also called a **map** of **f **which produces the result **Option****[A] => Option[B].**

def map[A, B](f: A => B): F[A] => F[B]

So, this is the pragmatic signature of the functors. But in Scala, we have a slightly different syntax of functors. Conceptually both have the same meaning, but the below signature is preferred in scala due to method chaining benefit i.e. we can chain multiple methods easily.

def map[A, B]( fa: F[A] )( f: A => B ): F[B] // First Signature

The above syntax of scala **map** method is available in scala pure functional libraries **scala-cats** and **scalaz**. But scala inbuilt functors have a different signature as below :

def map[B] ( f: A => B ): F[B] // Second Signature

This is because, in that case, the **map** method is created within a functor **F[A]**. This means that the input for **map** function is given by **F[A]** class examples like in scala we have **List**, **Option**, and **more** classes functors. If **List** or **Option** contains value(s), it will automatically pass to the **map** method.

But in the **first signature**, we will need to pass an object of **F[A]** within the **map** method but rest of the behavior is same. This method is useful when we don’t have any idea about the type of functor we will get, but we require to implement** A => B** on whatever functor is coming.

**Functors Law**

If we are creating our own functors, then the functor must follow these laws.

**Identity:**If we pass an**identity**function to the functor**map**method, then the functor must get back the original functor.**Composition:**If two functions execute sequentially like**( f andThen g ) ( x )**or**map( f ).map( g )**then the output must be equal to**g ( f ( x ) ).**

**Examples:**

**Example 1:** Create a custom **functor** trait which contains a method **map** and also create an instance of Functor of type List.

**Example 2:** In **Example 1**, we are creating our custom Functor trait and providing an implementation for map method, but **scala-cats** and **scalaz** provide us with inbuilt Functors and their implementation for predefine type like **List**, **Option** and **more**.

**References: **

- https://bartoszmilewski.com/2015/01/20/functors/
- https://www.youtube.com/watch?v=FyoQjkwsy7o&index=11&list=PLbgaMIhjbmEnaH_LTkxLI7FMa2HsnawM_
- https://typelevel.org/blog/2016/02/04/variance-and-functors.html
- https://typeclasses.com/contravariance

Reblogged this on Harmeet Singh(Taara).