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

scalaz.Zip.scala Maven / Gradle / Ivy

package scalaz

////
/**
 *
 */
////
trait Zip[F[_]]  { self =>
  ////
  def zip[A, B](a: => F[A], b: => F[B]): F[(A, B)]

  // derived functions

  /**The composition of Zip `F` and `G`, `[x]F[G[x]]`, is a Zip (if F is a Functor) */
  def compose[G[_]](implicit T0: Functor[F], G0: Zip[G]): Zip[λ[α => F[G[α]]]] =
    new CompositionZip[F, G] {
      implicit def T = T0
      implicit def F = self
      implicit def G = G0
    }

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

  def zipWith[A, B, C](fa: => F[A], fb: => F[B])(f: (A, B) => C)(implicit F: Functor[F]): F[C] =
    F.map(zip(fa, fb)) {
      case (a, b) => f(a, b)
    }

  def apzip[A, B](f: => F[A] => F[B], a: => F[A]): F[(A, B)] =
    zip(a, f(a))

  def apzipPL[A, B](f: => F[A] @?> F[B], a: => F[A])(implicit M: Monoid[F[B]]): F[(A, B)] =
    apzip(f.getOrZ(_), a)

  def ap(implicit F: Functor[F]): Apply[F] =
    new Apply[F] {
      def ap[A, B](fa: => F[A])(f: => F[A => B]) =
        zipWith(fa, f)((a, g) => g(a))
      def map[A, B](fa: F[A])(f: A => B) =
        F.map(fa)(f)
      override def apply2[A, B, C](fa: => F[A], fb: => F[B])(f: (A, B) => C) =
        zipWith(fa, fb)(f)
      override def tuple2[A, B](fa: => F[A], fb: => F[B]) =
        self.zip(fa, fb)
    }

  trait ZipLaw {
    /** Zipping preserves structure. */
    def zipPreservation[A](fa: F[A])(implicit FA: Equal[F[A]], F: Functor[F]): Boolean = {
      val fab = zip(fa, fa)
      FA.equal(F.map(fab)(_._1), fa) && FA.equal(F.map(fab)(_._2), fa)
    }

    def zipSymmetric[A, B](fa: F[A], fb: F[B])(implicit FA: Equal[F[A]], F: Functor[F]) =
      FA.equal(F.map(zip(fa, fb))(_._1), F.map(zip(fb, fa))(_._2))
  }
  def zipLaw = new ZipLaw {}

  ////
  val zipSyntax = new scalaz.syntax.ZipSyntax[F] { def F = Zip.this }
}

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

  ////

  def fzip[F[_], A, B](t: LazyTuple2[F[A], F[B]])(implicit F: Zip[F]): F[(A, B)] =
      F.zip(t._1, t._2)
  ////
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy