typelevel / algebra
1
package algebra.laws
2

3
import cats.kernel._
4
import cats.kernel.instances.option._
5

6
import org.typelevel.discipline.Laws
7

8
import org.scalacheck.{Arbitrary, Prop}
9
import org.scalacheck.Prop._
10

11
object GroupLaws {
12 3
  def apply[A : Eq : Arbitrary]: GroupLaws[A] = new GroupLaws[A] {
13 3
    def Equ = Eq[A]
14 3
    def Arb = implicitly[Arbitrary[A]]
15
  }
16
}
17

18
trait GroupLaws[A] extends Laws {
19

20
  implicit def Equ: Eq[A]
21
  implicit def Arb: Arbitrary[A]
22

23
  // groups
24

25 3
  def semigroup(implicit A: Semigroup[A]): GroupProperties = new GroupProperties(
26 3
    name = "semigroup",
27 3
    parents = Nil,
28 3
    Rules.serializable(A),
29 3
    Rules.associativity(A.combine),
30 3
    Rules.repeat1("combineN")(A.combineN),
31 3
    Rules.repeat2("combineN", "|+|")(A.combineN)(A.combine),
32 3
    "combineAllOption" -> forAll { (xs: Vector[A]) =>
33 3
      A.combineAllOption(xs) ?== xs.reduceOption(A.combine)
34
    }
35
  )
36

37 3
  def band(implicit A: Band[A]): GroupProperties = new GroupProperties(
38 3
    name = "band",
39 3
    parents = List(semigroup),
40 3
    Rules.idempotence(A.combine),
41 3
    "isIdempotent" -> Semigroup.isIdempotent[A]
42
  )
43

44 3
  def commutativeSemigroup(implicit A: CommutativeSemigroup[A]): GroupProperties = new GroupProperties(
45 3
    name = "commutative semigroup",
46 3
    parents = List(semigroup),
47 3
    Rules.commutative(A.combine)
48
  )
49

50 3
  def semilattice(implicit A: Semilattice[A]): GroupProperties = new GroupProperties(
51 3
    name = "semilattice",
52 3
    parents = List(band, commutativeSemigroup)
53
  )
54

55 3
  def monoid(implicit A: Monoid[A]): GroupProperties = new GroupProperties(
56 3
    name = "monoid",
57 3
    parents = List(semigroup),
58 3
    Rules.leftIdentity(A.empty)(A.combine),
59 3
    Rules.rightIdentity(A.empty)(A.combine),
60 3
    Rules.repeat0("combineN", "id", A.empty)(A.combineN),
61 3
    Rules.collect0("combineAll", "id", A.empty)(A.combineAll),
62 3
    Rules.isId("isEmpty", A.empty)(A.isEmpty),
63 3
    "combineAll" -> forAll { (xs: Vector[A]) =>
64 3
      A.combineAll(xs) ?== (A.empty +: xs).reduce(A.combine)
65
    }
66
  )
67

68 3
  def commutativeMonoid(implicit A: CommutativeMonoid[A]): GroupProperties = new GroupProperties(
69 3
    name = "commutative monoid",
70 3
    parents = List(monoid, commutativeSemigroup)
71
  )
72

73 3
  def boundedSemilattice(implicit A: BoundedSemilattice[A]): GroupProperties = new GroupProperties(
74 3
    name = "boundedSemilattice",
75 3
    parents = List(commutativeMonoid, semilattice)
76
  )
77

78 3
  def group(implicit A: Group[A]): GroupProperties = new GroupProperties(
79 3
    name = "group",
80 3
    parents = List(monoid),
81 3
    Rules.leftInverse(A.empty)(A.combine)(A.inverse),
82 3
    Rules.rightInverse(A.empty)(A.combine)(A.inverse),
83 3
    Rules.consistentInverse("remove")(A.remove)(A.combine)(A.inverse)
84
  )
85

86 3
  def commutativeGroup(implicit A: CommutativeGroup[A]): GroupProperties = new GroupProperties(
87 3
    name = "commutative group",
88 3
    parents = List(group, commutativeMonoid)
89
  )
90

91
  // property classes
92

93
  class GroupProperties(
94
    val name: String,
95
    val parents: Seq[GroupProperties],
96
    val props: (String, Prop)*
97
  ) extends RuleSet {
98 3
    val bases = Nil
99
  }
100
}

Read our documentation on viewing source code .

Loading