PageRenderTime 26ms CodeModel.GetById 12ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/core/src/main/scala/scalaz/Bifunctor.scala

http://github.com/scalaz/scalaz
Scala | 100 lines | 56 code | 23 blank | 21 comment | 0 complexity | 933a3ab2c3e1badad494154189ecfc30 MD5 | raw file
  1package scalaz
  2
  3////
  4/**
  5 * A type giving rise to two unrelated [[scalaz.Functor]]s.
  6 */
  7////
  8trait Bifunctor[F[_, _]]  { self =>
  9  ////
 10
 11  /** `map` over both type parameters. */
 12  def bimap[A, B, C, D](fab: F[A, B])(f: A => C, g: B => D): F[C, D]
 13
 14  /**The composition of Bifunctors `F` and `G`, `[x,y]F[G[x,y],G[x,y]]`, is a Bifunctor */
 15  def compose[G[_, _]](implicit G0: Bifunctor[G]): Bifunctor[λ[(α, β) => F[G[α, β], G[α, β]]]] =
 16    new CompositionBifunctor[F, G] {
 17      implicit def F = self
 18      implicit def G = G0
 19    }
 20
 21  /**The product of Bifunctors `F` and `G`, `[x,y](F[x,y], G[x,y])`, is a Bifunctor */
 22  def product[G[_, _]](implicit G0: Bifunctor[G]): Bifunctor[λ[(α, β) => (F[α, β], G[α, β])]] =
 23    new ProductBifunctor[F, G] {
 24      implicit def F = self
 25      implicit def G = G0
 26    }
 27
 28  /** Extract the Functor on the first param. */
 29  def leftFunctor[X]: Functor[F[*, X]] =
 30    new LeftFunctor[F, X] {val F = self}
 31
 32  def leftMap[A, B, C](fab: F[A, B])(f: A => C): F[C, B] =
 33    bimap(fab)(f, z => z)
 34
 35  /** Extract the Functor on the second param. */
 36  def rightFunctor[X]: Functor[F[X, *]] =
 37    new RightFunctor[F, X] {val F = self}
 38
 39  /** Unify the functor over both params. */
 40  def uFunctor: Functor[λ[α => F[α, α]]] =
 41    new UFunctor[F] {val F = self}
 42
 43  def rightMap[A, B, D](fab: F[A, B])(g: B => D): F[A, D] =
 44    bimap(fab)(z => z, g)
 45
 46  def umap[A, B](faa: F[A, A])(f: A => B): F[B, B] =
 47    bimap(faa)(f, f)
 48
 49  /** Embed two Functors , one on each side */
 50  def embed[G[_],H[_]](implicit G0: Functor[G], H0: Functor[H]): Bifunctor[λ[(α, β) => F[G[α],H[β]]]] =
 51    new CompositionBifunctorFunctors[F,G,H] {
 52      def F = self
 53      def G = G0
 54      def H = H0
 55    }
 56
 57  /** Embed one Functor to the left */
 58  def embedLeft[G[_]](implicit G0: Functor[G]): Bifunctor[λ[(α, β) => F[G[α],β]]] =
 59    embed[G,Id.Id]
 60
 61  /** Embed one Functor to the right */
 62  def embedRight[H[_]](implicit H0: Functor[H]): Bifunctor[λ[(α, β) => F[α,H[β]]]] =
 63    embed[Id.Id,H]
 64
 65  /** Bifunctors are covariant by nature */
 66  def widen[A, B, C >: A, D >: B](fab: F[A, B]): F[C, D] =
 67    bimap(fab)(identity[C], identity[D])
 68
 69  ////
 70  val bifunctorSyntax: scalaz.syntax.BifunctorSyntax[F] =
 71    new scalaz.syntax.BifunctorSyntax[F] { def F = Bifunctor.this }
 72}
 73
 74object Bifunctor {
 75  @inline def apply[F[_, _]](implicit F: Bifunctor[F]): Bifunctor[F] = F
 76
 77  import Isomorphism._
 78
 79  def fromIso[F[_, _], G[_, _]](D: F <~~> G)(implicit E: Bifunctor[G]): Bifunctor[F] =
 80    new IsomorphismBifunctor[F, G] {
 81      override def G: Bifunctor[G] = E
 82      override def iso: F <~~> G = D
 83    }
 84
 85  ////
 86
 87  ////
 88}
 89
 90trait IsomorphismBifunctor[F[_, _], G[_, _]] extends Bifunctor[F] {
 91  implicit def G: Bifunctor[G]
 92  ////
 93  import Isomorphism._
 94
 95  def iso: F <~~> G
 96
 97  override def bimap[A, B, C, D](fab: F[A, B])(f: A => C, g: B => D): F[C, D] =
 98    iso.from(G.bimap(iso.to(fab))(f, g))
 99  ////
100}