/core/src/main/scala/scalaz/Bifunctor.scala
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}