Skip to content
This repository has been archived by the owner on Feb 8, 2022. It is now read-only.

Commit

Permalink
Rename id/op/opInverse to empty/combine/uncombine.
Browse files Browse the repository at this point in the history
This seems like a good compromise.
  • Loading branch information
non committed Oct 26, 2013
1 parent 1a63823 commit e0ccca1
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 38 deletions.
20 changes: 11 additions & 9 deletions src/main/scala/algebra/Additive.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,31 @@ import scala.{ specialized => sp }

trait AdditiveSemigroup[@sp(Byte, Short, Int, Long, Float, Double) A] {
def additive: Semigroup[A] = new Semigroup[A] {
def op(x: A, y: A): A = plus(x, y)
def combine(x: A, y: A): A = plus(x, y)
}
def plus(x: A, y: A): A
}

trait AdditiveMonoid[@sp(Byte, Short, Int, Long, Float, Double) A] extends AdditiveSemigroup[A] {
override def additive: Monoid[A] = new Monoid[A] {
def id = zero
def op(x: A, y: A): A = plus(x, y)
def empty = zero
def combine(x: A, y: A): A = plus(x, y)
}
def zero: A
}

trait AdditiveCommutativeMonoid[@sp(Byte, Short, Int, Long, Float, Double) A] extends AdditiveMonoid[A] {
override def additive: CommutativeMonoid[A] = new CommutativeMonoid[A] {
def id = zero
def op(x: A, y: A): A = plus(x, y)
def empty = zero
def combine(x: A, y: A): A = plus(x, y)
}
}

trait AdditiveGroup[@sp(Byte, Short, Int, Long, Float, Double) A] extends AdditiveMonoid[A] {
override def additive: Group[A] = new Group[A] {
def id = zero
def op(x: A, y: A): A = plus(x, y)
def empty = zero
def combine(x: A, y: A): A = plus(x, y)
override def uncombine(x: A, y: A): A = minus(x, y)
def inverse(x: A): A = negate(x)
}

Expand All @@ -37,8 +38,9 @@ trait AdditiveGroup[@sp(Byte, Short, Int, Long, Float, Double) A] extends Additi

trait AdditiveCommutativeGroup[@sp(Byte, Short, Int, Long, Float, Double) A] extends AdditiveGroup[A] with AdditiveCommutativeMonoid[A] {
override def additive: CommutativeGroup[A] = new CommutativeGroup[A] {
def id = zero
def op(x: A, y: A): A = plus(x, y)
def empty = zero
def combine(x: A, y: A): A = plus(x, y)
override def uncombine(x: A, y: A): A = minus(x, y)
def inverse(x: A): A = negate(x)
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/main/scala/algebra/Group.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,21 @@ import scala.{ specialized => sp }
*/
trait Group[@sp(Byte, Short, Int, Long, Float, Double) A] extends Monoid[A] {
def inverse(a: A): A
def opInverse(a: A, b: A): A = op(a, inverse(b))
def uncombine(a: A, b: A): A = combine(a, inverse(b))

/**
* Return `a` appended to itself `n` times. If `n` is negative, then
* this returns `-a` appended to itself `n` times.
*/
override def sumn(a: A, n: Int): A =
if (n < 0) positiveSumn(inverse(a), -n)
else if (n == 0) id
else if (n == 0) empty
else positiveSumn(a, n)
}

trait GroupFunctions extends MonoidFunctions {
def inverse[A](a: A)(implicit ev: Group[A]): A = ev.inverse(a)
def opInverse[A](x: A, y: A)(implicit ev: Group[A]): A = ev.opInverse(x, y)
def uncombine[A](x: A, y: A)(implicit ev: Group[A]): A = ev.uncombine(x, y)
}

object Group extends GroupFunctions {
Expand Down
12 changes: 6 additions & 6 deletions src/main/scala/algebra/Monoid.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,28 @@ import scala.{ specialized => sp }
/**
* A monoid is a semigroup with an identity. A monoid is a specialization of a
* semigroup, so its operation must be associative. Additionally,
* `op(x, id) == op(id, x) == x`. For example, if we have `Monoid[String]`,
* with `op` as string concatenation, then `id = ""`.
* `combine(x, empty) == combine(empty, x) == x`. For example, if we have `Monoid[String]`,
* with `combine` as string concatenation, then `empty = ""`.
*/
trait Monoid[@sp(Boolean, Byte, Short, Int, Long, Float, Double) A] extends Semigroup[A] {
def id: A
def empty: A

/**
* Return `a` appended to itself `n` times.
*/
override def sumn(a: A, n: Int): A =
if (n < 0) throw new IllegalArgumentException("Repeated summation for monoids must have reptitions >= 0")
else if (n == 0) id
else if (n == 0) empty
else positiveSumn(a, n)

/**
* Given a sequence of `as`, sum them using the monoid and return the total.
*/
def sum(as: TraversableOnce[A]): A = as.foldLeft(id)(op)
def sum(as: TraversableOnce[A]): A = as.foldLeft(empty)(combine)
}

trait MonoidFunctions extends SemigroupFunctions {
def id[A](implicit ev: Monoid[A]): A = ev.id
def empty[A](implicit ev: Monoid[A]): A = ev.empty

def sum[A](as: TraversableOnce[A])(implicit ev: Monoid[A]): A = ev.sum(as)
}
Expand Down
20 changes: 11 additions & 9 deletions src/main/scala/algebra/Multiplicative.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import scala.{ specialized => sp }

trait MultiplicativeSemigroup[@sp(Byte, Short, Int, Long, Float, Double) A] {
def multiplicative: Semigroup[A] = new Semigroup[A] {
def op(x: A, y: A): A = times(x, y)
def combine(x: A, y: A): A = times(x, y)
}

def times(x: A, y: A): A
Expand All @@ -16,8 +16,8 @@ trait MultiplicativeSemigroup[@sp(Byte, Short, Int, Long, Float, Double) A] {

trait MultiplicativeMonoid[@sp(Byte, Short, Int, Long, Float, Double) A] extends MultiplicativeSemigroup[A] {
override def multiplicative: Monoid[A] = new Monoid[A] {
def id = one
def op(x: A, y: A): A = times(x, y)
def empty = one
def combine(x: A, y: A): A = times(x, y)
}

def one: A
Expand All @@ -29,15 +29,16 @@ trait MultiplicativeMonoid[@sp(Byte, Short, Int, Long, Float, Double) A] extends

trait MultiplicativeCommutativeMonoid[@sp(Byte, Short, Int, Long, Float, Double) A] extends MultiplicativeMonoid[A] {
override def multiplicative: CommutativeMonoid[A] = new CommutativeMonoid[A] {
def id = one
def op(x: A, y: A): A = times(x, y)
def empty = one
def combine(x: A, y: A): A = times(x, y)
}
}

trait MultiplicativeGroup[@sp(Byte, Short, Int, Long, Float, Double) A] extends MultiplicativeMonoid[A] {
override def multiplicative: Group[A] = new Group[A] {
def id = one
def op(x: A, y: A): A = times(x, y)
def empty = one
def combine(x: A, y: A): A = times(x, y)
override def uncombine(x: A, y: A): A = div(x, y)
def inverse(x: A): A = reciprocal(x)
}

Expand All @@ -50,8 +51,9 @@ trait MultiplicativeGroup[@sp(Byte, Short, Int, Long, Float, Double) A] extends

trait MultiplicativeCommutativeGroup[@sp(Byte, Short, Int, Long, Float, Double) A] extends MultiplicativeGroup[A] with MultiplicativeCommutativeMonoid[A] {
override def multiplicative: CommutativeGroup[A] = new CommutativeGroup[A] {
def id = one
def op(x: A, y: A): A = times(x, y)
def empty = one
def combine(x: A, y: A): A = times(x, y)
override def uncombine(x: A, y: A): A = div(x, y)
def inverse(x: A): A = reciprocal(x)
}
}
Expand Down
18 changes: 9 additions & 9 deletions src/main/scala/algebra/Semigroup.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import scala.{ specialized => sp }
import scala.annotation.{ switch, tailrec }

/**
* A semigroup is any set `A` with an associative operation (`op`).
* A semigroup is any set `A` with an associative operation (`combine`).
*/
trait Semigroup[@sp(Boolean, Byte, Short, Int, Long, Float, Double) A] {
def op(x: A, y: A): A
def combine(x: A, y: A): A

/**
* Return `a` appended to itself `n` times.
Expand All @@ -20,8 +20,8 @@ trait Semigroup[@sp(Boolean, Byte, Short, Int, Long, Float, Double) A] {
@tailrec def loop(b: A, k: Int, extra: A): A =
(k: @annotation.switch) match {
case 0 => b
case 1 => op(b, extra)
case n => loop(op(b, b), k >>> 1, if ((k & 1) == 1) op(b, extra) else extra)
case 1 => combine(b, extra)
case n => loop(combine(b, b), k >>> 1, if ((k & 1) == 1) combine(b, extra) else extra)
}
loop(a, n - 1, a)
}
Expand All @@ -31,15 +31,15 @@ trait Semigroup[@sp(Boolean, Byte, Short, Int, Long, Float, Double) A] {
*
* If the sequence is empty, returns None. Otherwise, returns Some(total).
*/
def sumOption(as: TraversableOnce[A]): Option[A] = as.reduceOption(op)
def sumOption(as: TraversableOnce[A]): Option[A] = as.reduceOption(combine)
}

trait SemigroupFunctions {
def op[@sp(Boolean,Byte,Short,Int,Long,Float,Double) A](x: A, y: A)(implicit ev: Semigroup[A]): A =
ev.op(x, y)
def combine[@sp(Boolean,Byte,Short,Int,Long,Float,Double) A](x: A, y: A)(implicit ev: Semigroup[A]): A =
ev.combine(x, y)

def maybeOp[@sp(Boolean,Byte,Short,Int,Long,Float,Double) A](ox: Option[A], y: A)(implicit ev: Semigroup[A]): A =
ox.map(x => ev.op(x, y)).getOrElse(y)
def maybeCombine[@sp(Boolean,Byte,Short,Int,Long,Float,Double) A](ox: Option[A], y: A)(implicit ev: Semigroup[A]): A =
ox.map(x => ev.combine(x, y)).getOrElse(y)

def sumn[@sp(Boolean,Byte,Short,Int,Long,Float,Double) A](a: A, n: Int)(implicit ev: Semigroup[A]): A =
ev.sumn(a, n)
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/algebra/Sign.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ object Sign {
if (i == 0) Zero else if (i > 0) Positive else Negative

implicit final val SignAlgebra = new Group[Sign] with Signed[Sign] with Order[Sign] {
def id: Sign = Zero
def op(a: Sign, b: Sign): Sign = Sign(a.toInt * b.toInt)
def empty: Sign = Zero
def combine(a: Sign, b: Sign): Sign = Sign(a.toInt * b.toInt)
def inverse(a: Sign): Sign = Sign(-a.toInt)
override def sign(a: Sign): Sign = a
def signum(a: Sign): Int = a.toInt
Expand Down

0 comments on commit e0ccca1

Please sign in to comment.