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

scalaz.Divisible.scala Maven / Gradle / Ivy

The newest version!
package scalaz

////
/** `Divisible` is the contravariant analogue of `scalaz.Applicative`
 *
 * @see [[https://github.com/ekmett/contravariant/blob/v1.3.2/src/Data/Functor/Contravariant/Divisible.hs]]
 * @see [[https://youtu.be/cB8DapKQz-I?t=20m35s ZuriHac 2015 - Discrimination is Wrong: Improving Productivity]]
 */
////
trait Divisible[F[_]] extends Divide[F] with InvariantApplicative[F] { self =>
  ////
  /** Universally quantified instance of F[_] */
  def conquer[A]: F[A]

  override def contramap[A, B](fa: F[A])(f: B => A): F[B] =
    divide2(conquer[Unit], fa)(c => ((), f(c)))

  override def xproduct0[Z](z: =>Z): F[Z] = conquer
  override def xproduct1[Z, A1](a1: =>F[A1])(f: A1 => Z, g: Z => A1): F[Z] = xmap(a1, f, g)
  override def xproduct2[Z, A1, A2](a1: =>F[A1], a2: =>F[A2])(
    f: (A1, A2) => Z,
    g: Z => (A1, A2)
  ): F[Z] = divide2(a1, a2)(g)
  override def xproduct3[Z, A1, A2, A3](a1: =>F[A1], a2: =>F[A2], a3: =>F[A3])(
    f: (A1, A2, A3) => Z,
    g: Z => (A1, A2, A3)
  ): F[Z] = divide3(a1, a2, a3)(g)
  override def xproduct4[Z, A1, A2, A3, A4](a1: =>F[A1], a2: =>F[A2], a3: =>F[A3], a4: =>F[A4])(
    f: (A1, A2, A3, A4) => Z,
    g: Z => (A1, A2, A3, A4)
  ): F[Z] = divide4(a1, a2, a3, a4)(g)

  trait DivisibleLaw extends DivideLaw {
    def rightIdentity[A](fa: F[A])(implicit E: Equal[F[A]]): Boolean =
      E.equal(divide(fa, conquer[A])(delta), fa)

    def leftIdentity[A](fa: F[A])(implicit E: Equal[F[A]]): Boolean =
      E.equal(divide(conquer[A], fa)(delta), fa)
  }

  def divisibleLaw: DivisibleLaw = new DivisibleLaw {}

  ////
  val divisibleSyntax: scalaz.syntax.DivisibleSyntax[F] =
    new scalaz.syntax.DivisibleSyntax[F] { def F = Divisible.this }
}

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

  import Isomorphism._

  def fromIso[F[_], G[_]](D: F <~> G)(implicit E: Divisible[G]): Divisible[F] =
    new IsomorphismDivisible[F, G] {
      override def G: Divisible[G] = E
      override def iso: F <~> G = D
    }

  ////

  ////
}

trait IsomorphismDivisible[F[_], G[_]] extends Divisible[F] with IsomorphismDivide[F, G] with IsomorphismInvariantApplicative[F, G]{
  implicit def G: Divisible[G]
  ////

  override def conquer[A]: F[A] =
    iso.from(G.conquer)

  override def xproduct0[Z](z: => Z): F[Z] =
    super[Divisible].xproduct0(z)
  override def xproduct1[Z, A1](a1: =>F[A1])(f: A1 => Z, g: Z => A1): F[Z] =
    super[Divisible].xproduct1(a1)(f, g)
  override def xproduct2[Z, A1, A2](a1: => F[A1], a2: => F[A2])(f: (A1, A2) => Z, g: Z => (A1, A2)): F[Z] =
    super[Divisible].xproduct2(a1, a2)(f, g)
  override def xproduct3[Z, A1, A2, A3](a1: => F[A1], a2: => F[A2], a3: => F[A3])(f: (A1, A2, A3) => Z, g: Z => (A1, A2, A3)): F[Z] =
    super[Divisible].xproduct3(a1, a2, a3)(f, g)
  override def xproduct4[Z, A1, A2, A3, A4](a1: => F[A1], a2: => F[A2], a3: => F[A3], a4: => F[A4])(f: (A1, A2, A3, A4) => Z, g: Z => (A1, A2, A3, A4)): F[Z] =
    super[Divisible].xproduct4(a1, a2, a3, a4)(f, g)

  ////
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy