Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce cats-kernel and remove algebra dependency #1001

Merged
merged 19 commits into from
Apr 29, 2016
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,11 @@ lazy val catsDoctestSettings = Seq(
) ++ doctestSettings

lazy val kernelSettings = Seq(
scalacOptions ++= commonScalacOptions,
scalacOptions ++= commonScalacOptions.filter(_ != "-Ywarn-value-discard"),
resolvers ++= Seq(
"bintray/non" at "http://dl.bintray.com/non/maven",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this used for?

Copy link
Contributor Author

@non non Apr 25, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That may not be necessary -- I'm not sure what we're using it for. I'll try removing it.

Resolver.sonatypeRepo("releases"),
Resolver.sonatypeRepo("snapshots")
),
Resolver.sonatypeRepo("snapshots")),
parallelExecution in Test := false,
scalacOptions in (Compile, doc) := (scalacOptions in (Compile, doc)).value.filter(_ != "-Xfatal-warnings")
) ++ warnUnusedImport
Expand Down
85 changes: 9 additions & 76 deletions core/src/main/scala/cats/std/anyval.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package cats
package std

import cats.kernel.CommutativeGroup

trait AnyValInstances
extends IntInstances
with ByteInstances
Expand All @@ -15,102 +13,37 @@ trait AnyValInstances
with UnitInstances

trait IntInstances extends cats.kernel.std.IntInstances {

implicit val intShow: Show[Int] =
Show.fromToString[Int]

implicit val intGroup: CommutativeGroup[Int] =
new CommutativeGroup[Int] {
def combine(x: Int, y: Int): Int = x + y
def empty: Int = 0
def inverse(x: Int): Int = -x
override def remove(x: Int, y: Int): Int = x - y
}
implicit val intShow: Show[Int] = Show.fromToString[Int]
}

trait ByteInstances extends cats.kernel.std.ByteInstances {

implicit val byteShow: Show[Byte] =
Show.fromToString[Byte]

implicit val byteGroup: CommutativeGroup[Byte] =
new CommutativeGroup[Byte] {
def combine(x: Byte, y: Byte): Byte = (x + y).toByte
def empty: Byte = 0
def inverse(x: Byte): Byte = (-x).toByte
override def remove(x: Byte, y: Byte): Byte = (x - y).toByte
}
implicit val byteShow: Show[Byte] = Show.fromToString[Byte]
}

trait CharInstances extends cats.kernel.std.CharInstances {
implicit val charShow: Show[Char] =
Show.fromToString[Char]
implicit val charShow: Show[Char] = Show.fromToString[Char]
}

trait ShortInstances extends cats.kernel.std.ShortInstances {

implicit val shortShow: Show[Short] =
Show.fromToString[Short]

implicit val shortGroup: CommutativeGroup[Short] =
new CommutativeGroup[Short] {
def combine(x: Short, y: Short): Short = (x + y).toShort
def empty: Short = 0
def inverse(x: Short): Short = (-x).toShort
override def remove(x: Short, y: Short): Short = (x - y).toShort
}
implicit val shortShow: Show[Short] = Show.fromToString[Short]
}

trait LongInstances extends cats.kernel.std.LongInstances {

implicit val longShow: Show[Long] =
Show.fromToString[Long]

implicit val longGroup: CommutativeGroup[Long] =
new CommutativeGroup[Long] {
def combine(x: Long, y: Long): Long = x + y
def empty: Long = 0L
def inverse(x: Long): Long = -x
override def remove(x: Long, y: Long): Long = x - y
}
implicit val longShow: Show[Long] = Show.fromToString[Long]
}

trait FloatInstances extends cats.kernel.std.FloatInstances {

implicit val floatShow: Show[Float] =
Show.fromToString[Float]

implicit val floatGroup: CommutativeGroup[Float] =
new CommutativeGroup[Float] {
def combine(x: Float, y: Float): Float = x + y
def empty: Float = 0F
def inverse(x: Float): Float = -x
override def remove(x: Float, y: Float): Float = x - y
}
implicit val floatShow: Show[Float] = Show.fromToString[Float]
}

trait DoubleInstances extends cats.kernel.std.DoubleInstances {

implicit val doubleShow: Show[Double] =
Show.fromToString[Double]

implicit val doubleGroup: CommutativeGroup[Double] =
new CommutativeGroup[Double] {
def combine(x: Double, y: Double): Double = x + y
def empty: Double = 0D
def inverse(x: Double): Double = -x
override def remove(x: Double, y: Double): Double = x - y
}
implicit val doubleShow: Show[Double] = Show.fromToString[Double]
}

trait BooleanInstances extends cats.kernel.std.BooleanInstances {

implicit val booleanShow: Show[Boolean] =
Show.fromToString[Boolean]
implicit val booleanShow: Show[Boolean] = Show.fromToString[Boolean]
}

trait UnitInstances extends cats.kernel.std.UnitInstances {

implicit val unitShow: Show[Unit] =
Show.fromToString[Unit]
implicit val unitShow: Show[Unit] = Show.fromToString[Unit]
}
49 changes: 0 additions & 49 deletions kernel-laws/src/main/scala/cats/kernel/laws/GroupLaws.scala
Original file line number Diff line number Diff line change
Expand Up @@ -81,45 +81,6 @@ trait GroupLaws[A] extends Laws {
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(
Expand All @@ -129,14 +90,4 @@ trait GroupLaws[A] extends Laws {
) 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)
// }

}
2 changes: 1 addition & 1 deletion kernel-laws/src/main/scala/cats/kernel/laws/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Prop.{False, Proof, Result}

package object laws {

implicit def PredicateFromMonoid[A](implicit ev: Eq[A], A: Monoid[A]): Predicate[A] =
implicit def nonEmptyPredicate[A](implicit ev: Eq[A], A: Monoid[A]): Predicate[A] =
new Predicate[A] {
def apply(a: A) = ev.neqv(a, A.empty)
}
Expand Down
15 changes: 14 additions & 1 deletion kernel/src/main/scala/cats/kernel/Group.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,24 @@ trait Group[@sp(Int, Long, Float, Double) A] extends Any with Monoid[A] {
* Return `a` appended to itself `n` times. If `n` is negative, then
* this returns `inverse(a)` appended to itself `n` times.
*/
override def combineN(a: A, n: Int): A =
override def combineN(a: A, n: Int): A = {
// This method is a bit tricky. Normally, to sum x a negative
// number of times (n), we can sum (-x) a positive number of times
// (-n). The issue here is that Int.MinValue cannot be negated; in
// other words (-MinValue) == MinValue.
//
// To work around that, we rely on the fact that we can divide n
// by 2 if we sum 2a (i.e. combine(a, a)) instead. Here is the
// transformation we use:
//
// combineN(x, -2147483648)
// combineN(combine(x, x), -1073741824)
// combineN(inverse(combine(x, x)), 1073741824)
if (n > 0) repeatedCombineN(a, n)
else if (n == 0) empty
else if (n == Int.MinValue) combineN(inverse(combine(a, a)), 1073741824)
Copy link
Contributor

@johnynek johnynek Apr 25, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is due to:

  1. - Int.MinValue == Int.MinValue
  2. combineN(x, n) == combineN(inverse(x), -n) except for n == Int.MinValue due to the above.
  3. combineN(x, n*n) = combineN(combine(x, x), n)

So, 1073741824 == -(Int.MaxValue / 2)

Can we add some verbosity to the comments?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure.

else repeatedCombineN(inverse(a), -n)
}
}

trait GroupFunctions[G[T] <: Group[T]] extends MonoidFunctions[Group] {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expand Down
23 changes: 12 additions & 11 deletions kernel/src/main/scala/cats/kernel/Order.scala
Original file line number Diff line number Diff line change
Expand Up @@ -177,13 +177,14 @@ object Order extends OrderFunctions {
/**
* An `Order` instance that considers all `A` instances to be equal.
*/
def allEqual[A]: Order[A] = new Order[A] {
def compare(x: A, y: A): Int = 0
}
def allEqual[A]: Order[A] =
new Order[A] {
def compare(x: A, y: A): Int = 0
}


/**
* A `Monoid[Order[A]]` can be generated for all `A` with the following
* A `Band[Order[A]]` can be generated for all `A` with the following
* properties:
*
* `empty` returns a trivial `Order[A]` which considers all `A` instances to
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning nitpicky comment: empty comes from Monoid not Band, so we may want to adjust the previous line of the comment to mention both Band and Monoid.

Expand All @@ -194,16 +195,16 @@ object Order extends OrderFunctions {
*
* @see [[Order.whenEqual]]
*/
def whenEqualMonoid[A]: Monoid[Order[A]] =
new Monoid[Order[A]] {
def whenEqualMonoid[A]: Band[Order[A]] =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want Band[Order[A]] with Monoid[Order[A]] Band does not have empty but BoundedSemilattice is commutative.

new Band[Order[A]] {
val empty: Order[A] = allEqual[A]

def combine(x: Order[A], y: Order[A]): Order[A] = x whenEqual y
}

def fromOrdering[A](implicit ev: Ordering[A]): Order[A] = new Order[A] {
def compare(x: A, y: A): Int = ev.compare(x, y)
def fromOrdering[A](implicit ev: Ordering[A]): Order[A] =
new Order[A] {
def compare(x: A, y: A): Int = ev.compare(x, y)

override def toOrdering: Ordering[A] = ev
}
override def toOrdering: Ordering[A] = ev
}
}
9 changes: 9 additions & 0 deletions kernel/src/main/scala/cats/kernel/std/bigInt.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ package object bigInt extends BigIntInstances
trait BigIntInstances {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not Ring here? (or is there no ring?) or at least Group.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a CommutativeGroup.

implicit val bigIntOrder: Order[BigInt] =
new BigIntOrder
implicit val bigIntGroup: CommutativeGroup[BigInt] =
new BigIntGroup
}

class BigIntGroup extends CommutativeGroup[BigInt] {
val empty: BigInt = BigInt(0)
def combine(x: BigInt, y: BigInt): BigInt = x + y
def inverse(x: BigInt): BigInt = -x
override def remove(x: BigInt, y: BigInt): BigInt = x - y
}

class BigIntOrder extends Order[BigInt] {
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/main/scala/cats/kernel/std/boolean.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package std
package object boolean extends BooleanInstances

trait BooleanInstances {
implicit val booleanOrder: BooleanOrder =
implicit val booleanOrder: Order[Boolean] =
new BooleanOrder
}

Expand Down
8 changes: 8 additions & 0 deletions kernel/src/main/scala/cats/kernel/std/byte.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ package object byte extends ByteInstances

trait ByteInstances {
implicit val byteOrder: Order[Byte] = new ByteOrder
implicit val byteGroup: CommutativeGroup[Byte] = new ByteGroup
}

class ByteGroup extends CommutativeGroup[Byte] {
def combine(x: Byte, y: Byte): Byte = (x + y).toByte
def empty: Byte = 0
def inverse(x: Byte): Byte = (-x).toByte
override def remove(x: Byte, y: Byte): Byte = (x - y).toByte
}

class ByteOrder extends Order[Byte] {
Expand Down
8 changes: 8 additions & 0 deletions kernel/src/main/scala/cats/kernel/std/double.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ import java.lang.Math

trait DoubleInstances {
implicit val doubleOrder: Order[Double] = new DoubleOrder
implicit val doubleGroup: CommutativeGroup[Double] = new DoubleGroup
}

class DoubleGroup extends CommutativeGroup[Double] {
def combine(x: Double, y: Double): Double = x + y
def empty: Double = 0D
def inverse(x: Double): Double = -x
override def remove(x: Double, y: Double): Double = x - y
}

class DoubleOrder extends Order[Double] {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strictly, is this a PartialOrder due to NaN? Should we maybe have that and some unsafeToOrder method for people to opt out?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation is using java.lang.Double.compare which means it is total (but ugly) -- NaN is greater than all non-NaN values:

scala> java.lang.Double.compare(Double.NaN, Double.PositiveInfinity)
res4: Int = 1
scala> java.lang.Double.compare(Double.NaN, Double.NaN)
res7: Int = 0

Expand Down
13 changes: 12 additions & 1 deletion kernel/src/main/scala/cats/kernel/std/float.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,18 @@ package cats.kernel
package std

trait FloatInstances {
implicit val floatOrder = new FloatOrder
implicit val floatOrder: Order[Float] = new FloatOrder
implicit val floatGroup: CommutativeGroup[Float] = new FloatGroup
}

/**
* This is only approximately associative.
*/
class FloatGroup extends CommutativeGroup[Float] {
def combine(x: Float, y: Float): Float = x + y
def empty: Float = 0F
def inverse(x: Float): Float = -x
override def remove(x: Float, y: Float): Float = x - y
}

/**
Expand Down
8 changes: 8 additions & 0 deletions kernel/src/main/scala/cats/kernel/std/int.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ package object int extends IntInstances

trait IntInstances {
implicit val intOrder: Order[Int] = new IntOrder
implicit val intGroup: CommutativeGroup[Int] = new IntGroup
}

class IntGroup extends CommutativeGroup[Int] {
def combine(x: Int, y: Int): Int = x + y
def empty: Int = 0
def inverse(x: Int): Int = -x
override def remove(x: Int, y: Int): Int = x - y
}

class IntOrder extends Order[Int] {
Expand Down
10 changes: 9 additions & 1 deletion kernel/src/main/scala/cats/kernel/std/long.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,15 @@ package std
package object long extends LongInstances

trait LongInstances {
implicit val longOrder = new LongOrder
implicit val longOrder: Order[Long] = new LongOrder
implicit val longGroup: CommutativeGroup[Long] = new LongGroup
}

class LongGroup extends CommutativeGroup[Long] {
def combine(x: Long, y: Long): Long = x + y
def empty: Long = 0L
def inverse(x: Long): Long = -x
override def remove(x: Long, y: Long): Long = x - y
}

class LongOrder extends Order[Long] {
Expand Down
Loading