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

scalaz.Decidable.scala Maven / Gradle / Ivy

package scalaz

////
// Copyright: 2017 Sam Halliday
// License: https://opensource.org/licenses/BSD-3-Clause

/**
 * Coproduct analogue of Divide
 *
 * https://hackage.haskell.org/package/contravariant-1.4.1/docs/Data-Functor-Contravariant-Divisible.html#t:Decidable
 */
////
trait Decidable[F[_]] extends Divisible[F] with InvariantAlt[F] { self =>
  ////

  final def choose[Z, A1, A2](a1: =>F[A1], a2: =>F[A2])(f: Z => A1 \/ A2): F[Z] = choose2(a1, a2)(f)

  def choose1[Z, A1](a1: =>F[A1])(f: Z => A1): F[Z] = contramap(a1)(f)
  def choose2[Z, A1, A2](a1: =>F[A1], a2: =>F[A2])(f: Z => A1 \/ A2): F[Z]
  def choose3[Z, A1, A2, A3](a1: =>F[A1], a2: =>F[A2], a3: =>F[A3])(
    f: Z => A1 \/ (A2 \/ A3)
  ): F[Z] = {
    val a23: F[A2 \/ A3] = choose2(a2, a3)(identity)
    choose2(a1, a23)(f)
  }
  def choose4[Z, A1, A2, A3, A4](a1: =>F[A1], a2: =>F[A2], a3: =>F[A3], a4: =>F[A4])(
    f: Z => A1 \/ (A2 \/ (A3 \/ A4))
  ): F[Z] = {
    val a234: F[A2 \/ (A3 \/ A4)] = choose3(a2, a3, a4)(identity)
    choose2(a1, a234)(f)
  }
  // ... chooseN

  final def choosing2[Z, A1, A2](
    f: Z => A1 \/ A2
  )(implicit fa1: F[A1], fa2: F[A2]): F[Z] =
    choose2(fa1, fa2)(f)
  final def choosing3[Z, A1, A2, A3](
    f: Z => A1 \/ (A2 \/ A3)
  )(implicit fa1: F[A1], fa2: F[A2], fa3: F[A3]): F[Z] =
    choose3(fa1, fa2, fa3)(f)
  final def choosing4[Z, A1, A2, A3, A4](
    f: Z => A1 \/ (A2 \/ (A3 \/ A4))
  )(implicit fa1: F[A1], fa2: F[A2], fa3: F[A3], fa4: F[A4]): F[Z] =
    choose4(fa1, fa2, fa3, fa4)(f)
  // ... choosingX

  override def xcoproduct1[Z, A1](a1: =>F[A1])(
    f: A1 => Z,
    g: Z => A1
  ): F[Z] = choose1(a1)(g)
  override def xcoproduct2[Z, A1, A2](a1: =>F[A1], a2: =>F[A2])(
    f: (A1 \/ A2) => Z,
    g: Z => (A1 \/ A2)
  ): F[Z] = choose2(a1, a2)(g)
  override def xcoproduct3[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] = choose3(a1, a2, a3)(g)
  override def xcoproduct4[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] = choose4(a1, a2, a3, a4)(g)


  trait DecidableLaw extends DivisibleLaw {
    // distribution law blocked on https://github.com/ekmett/contravariant/issues/53

    // TODO: translate this
    // choose f (choose g m n) o = divide f' m (divide id n o) where
    //   f' bcd = either (either id (Right . Left) . g) (Right . Right) . f
  }
  def decidableLaw: DecidableLaw = new DecidableLaw {}

  ////
  val decidableSyntax: scalaz.syntax.DecidableSyntax[F] =
    new scalaz.syntax.DecidableSyntax[F] { def F = Decidable.this }
}

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

  import Isomorphism._

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

  ////

  ////
}

trait IsomorphismDecidable[F[_], G[_]] extends Decidable[F] with IsomorphismDivisible[F, G] with IsomorphismInvariantAlt[F, G]{
  implicit def G: Decidable[G]
  ////

  def choose2[Z, A1, A2](a1: => F[A1], a2: => F[A2])(f: Z => A1 \/ A2): F[Z] =
    iso.from(G.choose2(iso.to(a1), iso.to(a2))(f))

  override def xcoproduct1[Z, A1](a1: => F[A1])(f: A1 => Z, g: Z => A1): F[Z] =
    super[Decidable].xcoproduct1(a1)(f, g)
  override def xcoproduct2[Z, A1, A2](a1: => F[A1], a2: => F[A2])(f: A1 \/ A2 => Z, g: Z => A1 \/ A2): F[Z] =
    super[Decidable].xcoproduct2(a1, a2)(f, g)
  override def xcoproduct3[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[Decidable].xcoproduct3(a1, a2, a3)(f, g)
  override def xcoproduct4[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[Decidable].xcoproduct4(a1, a2, a3, a4)(f, g)

  ////
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy