3 minutes

# Cats Bifunctor

The following will be a short and rather simple article about a useful function I recently learned about: `bimap`

by cats.

In cats and in some cases scala, types like Either, Validated, Option… are right biased. which means that when we call `.map`

on them, the function applied in the map is only applied on the case of a right.

Here are some examples:

```
val either: Either[String, Int] = Right(2)
val result: Either[String, Int] = either.map(int => int * 2)
val option1: Option[Int] = Some(2)
val result1: Option[Int] = option1.map(int => int * 2)
// a map on a None returns a None.
```

But what if we only wanted to apply a function on the left side? conveniently, cats offers us a `.leftMap`

function. This does not apply in the case of an option.

`val result = either.leftMap(str => "Error: " + str)`

In some cases, we find ourselves wanting to apply different functions in the case where the return is a right and when its a left. In that case we can use `bimap`

.

bimap is defined by a `Bifunctor`

and from the cats definition:

`Bifunctor takes two type parameters instead of one, and is a functor in both of these parameters. It defines a function bimap, which allows for mapping over both arguments at the same time. Its signature is as follows:`

`def bimap[A, B, C, D](fab: F[A, B])(f: A => C, g: B => D): F[C, D]`

here’s an example:

```
import cats.syntax.either._
val either: Either[String, Int] = ???
def function1(str: String) = ???
def function2(int: Int) = ???
either.bimap(function1, function2)
```

In the case where the value `either`

is of type Right then `function2`

will be applied. In the case its a Left, `function1`

would be applied.

Here is the implementation of `bimap`

on an either:

```
def bimap[C, D](fa: A => C, fb: B => D): Either[C, D] = eab match {
case Left(a) => Left(fa(a))
case Right(b) => Right(fb(b))
}
```

In case this behavior is a bit familiar its because scala offers a very similar function: `fold`

Similarly to `bimap`

, fold takes 2 functions and applies them on the left and the right.

Here is the scala doc along with the function definition:

```
/** Applies `fa` if this is a `Left` or `fb` if this is a `Right`.
*
* @example {{{
* val result = util.Try("42".toInt).toEither
* result.fold(
* e => s"Operation failed with $e",
* v => s"Operation produced value: $v"
* )
* }}}
*
* @param fa the function to apply if this is a `Left`
* @param fb the function to apply if this is a `Right`
* @return the results of applying the function
*/
def fold[C](fa: A => C, fb: B => C): C = this match {
case Right(b) => fb(b)
case Left(a) => fa(a)
}
```

The difference between both is in the return and in the return types of the function they take.

In the case of `bimap`

on an Either, the return type will compulsorily be an Either. So its as its name suggests, its a map in both directions. The return type is an Either and the 2 type parameters can be different from one another and from the initial type parameters.

But in the case of `fold`

, the return type will depend on the functions passed to the fold. In the same time, both functions will have to have the same return type (`C in the scala doc`

)

So to summarize the main differences between a bimap and a fold:

`bimap`

returns an Either while`fold`

’s return type depends on the functions passed to it.- The functions passed to the bimap can have different return types. while the functions passed to the fold needs to have the same return type.