```package scalaz

/**
* Binary covariant functor.
*
* <p>
* All binary functor instances must satisfy 2 laws:
* <ol>
* <li><strong>identity</strong><br/><code>forall a. a == bimap(a, identity, identity)</code></li>
* <li><strong>composition</strong><br/><code>forall a f g h i. bimap(a, f compose g, h compose i) == bimap(bimap(a, g, i), f, h)</code></li>
* </ol>
* </p>
*/
trait Bifunctor[F[_, _]] {
def bimap[A, B, C, D](k: F[A, B], f: A => C, g: B => D): F[C, D]
}

object Bifunctor {
import Scalaz._

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

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

implicit def ValidationBifunctor: Bifunctor[Validation] = new Bifunctor[Validation] {
def bimap[A, B, C, D](k: Validation[A, B], f: A => C, g: B => D) =
k match {
case Failure(a) => failure(f(a))
case Success(b) => success(g(b))
}
}

import java.util.Map.Entry
import java.util.AbstractMap.SimpleImmutableEntry

implicit def MapEntryBifunctor: Bifunctor[Entry] = new Bifunctor[Entry] {
def bimap[A, B, C, D](k: Entry[A, B], f: A => C, g: B => D) = new SimpleImmutableEntry(f(k.getKey), g(k.getValue))
}

}

```