# Bifunctor

This article will look at bifunctors, and how they can be used in the real world. This article assumes some knowlege of functors. A simple way to think about bifunctor is as a functor of two arguments.

A bifunctor is a type class of types which give rise to two independent, covariant functors. Some common uses of bifunctor include mapping over `Either` and `Tuple2` types. While functor provides a map operation that takes a function `A = >B` and applies that function over a context `F[A] => F[B]`, a bifunctor offers us the bimap operation which takes two functions `(A = >B, C => D)` and applies one or both of these functions over a context.

In Haskell, we can define a bifunctor as:

``````class Bifunctor (f:: * -> * -> *) where
bimap  :: (a -> b) -> (c -> d) -> f a c -> f b d
first  :: (a -> b) -> f a c -> f b c
second :: (b -> c) -> f a b -> f a c
{-# MINIMAL bimap | first, second #-}``````

A Scala implementation of `bimap` for both `Tuple2` and `Either`:

``````trait Functor[F[+_]] {
def map[A,B](a: F[A])(f: A => B): F[B]
}

trait Bifunctor[F[+_, +_]] {
def bimap[A, B, C, D](fa: F[A, B], f: A => C, g: B => D): F[C, D]
}

object Bifunctor {
implicit def Tuple2Bifunctor = new Bifunctor[Tuple2] {
def bimap[A, B, C, D](fa: (A, B), f: A => C, g: B => D) =
(f(fa._1), g(fa._2))
}

implicit def EitherBifunctor = new Bifunctor[Either] {
def bimap[A, B, C, D](fa: Either[A, B], f: A => C, g: B => D) =
fa match {
case Left(a) => Left(f(a))
case Right(b) => Right(g(b))
}
}
}``````