scalaz.Bifunctor.scala Maven / Gradle / Ivy
The newest version!
package scalaz
////
/**
* A type giving rise to two unrelated [[scalaz.Functor]]s.
*/
////
trait Bifunctor[F[_, _]] { self =>
////
/** `map` over both type parameters. */
def bimap[A, B, C, D](fab: F[A, B])(f: A => C, g: B => D): F[C, D]
/**The composition of Bifunctors `F` and `G`, `[x,y]F[G[x,y],G[x,y]]`, is a Bifunctor */
def compose[G[_, _]](implicit G0: Bifunctor[G]): Bifunctor[λ[(α, β) => F[G[α, β], G[α, β]]]] =
new CompositionBifunctor[F, G] {
override def F = self
override def G = G0
}
/**The product of Bifunctors `F` and `G`, `[x,y](F[x,y], G[x,y])`, is a Bifunctor */
def product[G[_, _]](implicit G0: Bifunctor[G]): Bifunctor[λ[(α, β) => (F[α, β], G[α, β])]] =
new ProductBifunctor[F, G] {
override def F = self
override def G = G0
}
/** Extract the Functor on the first param. */
def leftFunctor[X]: Functor[F[*, X]] =
new LeftFunctor[F, X] {val F = self}
def leftMap[A, B, C](fab: F[A, B])(f: A => C): F[C, B] =
bimap(fab)(f, z => z)
/** Extract the Functor on the second param. */
def rightFunctor[X]: Functor[F[X, *]] =
new RightFunctor[F, X] {val F = self}
/** Unify the functor over both params. */
def uFunctor: Functor[λ[α => F[α, α]]] =
new UFunctor[F] {val F = self}
def rightMap[A, B, D](fab: F[A, B])(g: B => D): F[A, D] =
bimap(fab)(z => z, g)
def umap[A, B](faa: F[A, A])(f: A => B): F[B, B] =
bimap(faa)(f, f)
/** Embed two Functors , one on each side */
def embed[G[_],H[_]](implicit G0: Functor[G], H0: Functor[H]): Bifunctor[λ[(α, β) => F[G[α],H[β]]]] =
new CompositionBifunctorFunctors[F,G,H] {
def F = self
def G = G0
def H = H0
}
/** Embed one Functor to the left */
def embedLeft[G[_]](implicit G0: Functor[G]): Bifunctor[λ[(α, β) => F[G[α],β]]] =
embed[G,Id.Id]
/** Embed one Functor to the right */
def embedRight[H[_]](implicit H0: Functor[H]): Bifunctor[λ[(α, β) => F[α,H[β]]]] =
embed[Id.Id,H]
/** Bifunctors are covariant by nature */
def widen[A, B, C >: A, D >: B](fab: F[A, B]): F[C, D] =
bimap(fab)(identity[C], identity[D])
////
val bifunctorSyntax: scalaz.syntax.BifunctorSyntax[F] =
new scalaz.syntax.BifunctorSyntax[F] { def F = Bifunctor.this }
}
object Bifunctor {
@inline def apply[F[_, _]](implicit F: Bifunctor[F]): Bifunctor[F] = F
import Isomorphism._
def fromIso[F[_, _], G[_, _]](D: F <~~> G)(implicit E: Bifunctor[G]): Bifunctor[F] =
new IsomorphismBifunctor[F, G] {
override def G: Bifunctor[G] = E
override def iso: F <~~> G = D
}
////
////
}
trait IsomorphismBifunctor[F[_, _], G[_, _]] extends Bifunctor[F] {
implicit def G: Bifunctor[G]
////
import Isomorphism._
def iso: F <~~> G
override def bimap[A, B, C, D](fab: F[A, B])(f: A => C, g: B => D): F[C, D] =
iso.from(G.bimap(iso.to(fab))(f, g))
////
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy