All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scalaz.Distributive.scala Maven / Gradle / Ivy

package scalaz

/** Dual of [[scalaz.Traverse]].  To transform `F[G[B]]` to `G[F[B]]`,
  * you may use `Traverse[F]` and `Applicative[G]`, but alternatively
  * `Functor[F]` and `Distributive[G]`, which permits greater sharing
  * and nonstrictness.
  */
trait Distributive[F[_]] extends Functor[F] { self =>
  def distributeImpl[G[_]:Functor,A,B](fa: G[A])(f: A => F[B]): F[G[B]]


  /**The composition of Distributives `F` and `G`, `[x]F[G[x]]`, is a Distributive */
  def compose[G[_]](implicit G0: Distributive[G]): Distributive[λ[α => F[G[α]]]] =
    new CompositionDistributive[F, G] {
      implicit def F = self
      implicit def G = G0
    }

  /**The product of Distributives `F` and `G`, `[x](F[x], G[x]])`, is a Distributive */
  def product[G[_]](implicit G0: Distributive[G]): Distributive[λ[α => (F[α], G[α])]] =
    new ProductDistributive[F, G] {
      implicit def F = self
      implicit def G = G0
    }

  class Distribution[G[_]](implicit G: Functor[G]) {
    def run[A,B](fa: G[A])(f: A => F[B]): F[G[B]] = distributeImpl(fa)(f)
  }

  def distribution[G[_]:Functor]: Distribution[G] =
    new Distribution[G]

  def distribute[G[_]:Functor,A,B](fa: G[A])(f: A => F[B]): F[G[B]] =
    distribution[G].run(fa)(f)

  def cosequence[G[_]:Functor,A](fa: G[F[A]]): F[G[A]] =
    distributeImpl(fa)(x => x)

}

object Distributive {
  @inline def apply[F[_]](implicit F: Distributive[F]): Distributive[F] = F

  // Distributive is the dual of Traverse.
  type Cotraverse[F[_]] =
  Distributive[F]
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy