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

cats.kernel.Semilattice.scala Maven / Gradle / Ivy

The newest version!
package cats.kernel

import scala.{specialized => sp}

/**
 * Semilattices are commutative semigroups whose operation
 * (i.e. combine) is also idempotent.
 */
trait Semilattice[@sp(Int, Long, Float, Double) A] extends Any with Band[A] with CommutativeSemigroup[A] { self =>

  /**
   * Given Eq[A], return a PartialOrder[A] using the `combine`
   * operator to determine the partial ordering. This method assumes
   * `combine` functions as `meet` (that is, as a lower bound).
   *
   * This method returns:
   *
   *    0.0 if x = y
   *   -1.0 if x = combine(x, y)
   *    1.0 if y = combine(x, y)
   *    NaN otherwise
   */
  def asMeetPartialOrder(implicit ev: Eq[A]): PartialOrder[A] =
    new PartialOrder[A] {
      def partialCompare(x: A, y: A): Double =
        if (ev.eqv(x, y)) 0.0
        else {
          val z = self.combine(x, y)
          if (ev.eqv(x, z)) -1.0 else if (ev.eqv(y, z)) 1.0 else Double.NaN
        }
    }

  /**
   * Given Eq[A], return a PartialOrder[A] using the `combine`
   * operator to determine the partial ordering. This method assumes
   * `combine` functions as `join` (that is, as an upper bound).
   *
   * This method returns:
   *
   *    0.0 if x = y
   *   -1.0 if y = combine(x, y)
   *    1.0 if x = combine(x, y)
   *    NaN otherwise
   */
  def asJoinPartialOrder(implicit ev: Eq[A]): PartialOrder[A] =
    new PartialOrder[A] {
      def partialCompare(x: A, y: A): Double =
        if (ev.eqv(x, y)) 0.0
        else {
          val z = self.combine(x, y)
          if (ev.eqv(y, z)) -1.0 else if (ev.eqv(x, z)) 1.0 else Double.NaN
        }
    }
}

abstract class SemilatticeFunctions[S[T] <: Semilattice[T]] extends SemigroupFunctions[S] {
  def asMeetPartialOrder[A](implicit s: S[A], ev: Eq[A]): PartialOrder[A] =
    s.asMeetPartialOrder(ev)
  def asJoinPartialOrder[A](implicit s: S[A], ev: Eq[A]): PartialOrder[A] =
    s.asJoinPartialOrder(ev)
}

object Semilattice extends SemilatticeFunctions[Semilattice] {

  /**
   * Access an implicit `Semilattice[A]`.
   */
  @inline final def apply[@sp(Int, Long, Float, Double) A](implicit ev: Semilattice[A]): Semilattice[A] = ev

  /**
   * Create a `Semilattice` instance from the given function.
   */
  @inline def instance[A](cmb: (A, A) => A): Semilattice[A] = new Semilattice[A] {
    override def combine(x: A, y: A): A = cmb(x, y)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy