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

algebra.laws.GroupLaws.scala Maven / Gradle / Ivy

The newest version!
package algebra.laws

import algebra._
import algebra.ring._

import org.typelevel.discipline.Laws

import org.scalacheck.{Arbitrary, Prop}
import org.scalacheck.Prop._

object GroupLaws {
  def apply[A : Eq : Arbitrary] = new GroupLaws[A] {
    def Equ = Eq[A]
    def Arb = implicitly[Arbitrary[A]]
  }
}

trait GroupLaws[A] extends Laws {

  implicit def Equ: Eq[A]
  implicit def Arb: Arbitrary[A]

  // groups

  def semigroup(implicit A: Semigroup[A]) = new GroupProperties(
    name = "semigroup",
    parents = Nil,
    Rules.serializable(A),
    Rules.associativity(A.combine),
    Rules.repeat1("combineN")(A.combineN),
    Rules.repeat2("combineN", "|+|")(A.combineN)(A.combine)
  )

  def band(implicit A: Band[A]) = new GroupProperties(
    name = "band",
    parents = List(semigroup),
    Rules.idempotence(A.combine),
    "isIdempotent" -> Semigroup.isIdempotent[A]
  )

  def commutativeSemigroup(implicit A: CommutativeSemigroup[A]) = new GroupProperties(
    name = "commutative semigroup",
    parents = List(semigroup),
    Rules.commutative(A.combine)
  )

  def semilattice(implicit A: Semilattice[A]) = new GroupProperties(
    name = "semilattice",
    parents = List(band, commutativeSemigroup)
  )

  def monoid(implicit A: Monoid[A]) = new GroupProperties(
    name = "monoid",
    parents = List(semigroup),
    Rules.leftIdentity(A.empty)(A.combine),
    Rules.rightIdentity(A.empty)(A.combine),
    Rules.repeat0("combineN", "id", A.empty)(A.combineN),
    Rules.collect0("combineAll", "id", A.empty)(A.combineAll),
    Rules.isId("isEmpty", A.empty)(A.isEmpty)
  )

  def commutativeMonoid(implicit A: CommutativeMonoid[A]) = new GroupProperties(
    name = "commutative monoid",
    parents = List(monoid, commutativeSemigroup)
  )

  def boundedSemilattice(implicit A: BoundedSemilattice[A]) = new GroupProperties(
    name = "boundedSemilattice",
    parents = List(commutativeMonoid, semilattice)
  )

  def group(implicit A: Group[A]) = new GroupProperties(
    name = "group",
    parents = List(monoid),
    Rules.leftInverse(A.empty)(A.combine)(A.inverse),
    Rules.rightInverse(A.empty)(A.combine)(A.inverse),
    Rules.consistentInverse("remove")(A.remove)(A.combine)(A.inverse)
  )

  def commutativeGroup(implicit A: CommutativeGroup[A]) = new GroupProperties(
    name = "commutative group",
    parents = List(group, commutativeMonoid)
  )

  // additive groups

  def additiveSemigroup(implicit A: AdditiveSemigroup[A]) = new AdditiveProperties(
    base = semigroup(A.additive),
    parents = Nil,
    Rules.serializable(A),
    Rules.repeat1("sumN")(A.sumN),
    Rules.repeat2("sumN", "+")(A.sumN)(A.plus)
  )

  def additiveCommutativeSemigroup(implicit A: AdditiveCommutativeSemigroup[A]) = new AdditiveProperties(
    base = commutativeSemigroup(A.additive),
    parents = List(additiveSemigroup)
  )

  def additiveMonoid(implicit A: AdditiveMonoid[A]) = new AdditiveProperties(
    base = monoid(A.additive),
    parents = List(additiveSemigroup),
    Rules.repeat0("sumN", "zero", A.zero)(A.sumN),
    Rules.collect0("sum", "zero", A.zero)(A.sum)
  )

  def additiveCommutativeMonoid(implicit A: AdditiveCommutativeMonoid[A]) = new AdditiveProperties(
    base = commutativeMonoid(A.additive),
    parents = List(additiveMonoid)
  )

  def additiveGroup(implicit A: AdditiveGroup[A]) = new AdditiveProperties(
    base = group(A.additive),
    parents = List(additiveMonoid),
    Rules.consistentInverse("subtract")(A.minus)(A.plus)(A.negate)
  )

  def additiveCommutativeGroup(implicit A: AdditiveCommutativeGroup[A]) = new AdditiveProperties(
    base = commutativeGroup(A.additive),
    parents = List(additiveGroup)
  )


  // property classes

  class GroupProperties(
    val name: String,
    val parents: Seq[GroupProperties],
    val props: (String, Prop)*
  ) extends RuleSet {
    val bases = Nil
  }

  class AdditiveProperties(
    val base: GroupProperties,
    val parents: Seq[AdditiveProperties],
    val props: (String, Prop)*
  ) extends RuleSet {
    val name = base.name
    val bases = List("base" -> base)
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy