diff --git a/cats/src/io/github/iltotore/iron/instances.scala b/cats/src/io/github/iltotore/iron/instances.scala index 7187b5a..76f952b 100644 --- a/cats/src/io/github/iltotore/iron/instances.scala +++ b/cats/src/io/github/iltotore/iron/instances.scala @@ -1,12 +1,12 @@ package io.github.iltotore.iron -import _root_.cats.kernel.{CommutativeSemigroup, Hash, LowerBounded, PartialOrder, UpperBounded} +import _root_.cats.kernel.{CommutativeMonoid, CommutativeSemigroup, Hash, LowerBounded, PartialOrder, UpperBounded} import _root_.cats.{Eq, Monoid, Order, Show, Traverse} import io.github.iltotore.iron.constraint.numeric.* import scala.util.NotGiven import _root_.cats.Functor import algebra.instances.all.* -import algebra.ring.AdditiveCommutativeSemigroup +import algebra.ring.{AdditiveCommutativeMonoid, AdditiveCommutativeSemigroup} /** * Represent all Cats' typeclass instances for Iron. @@ -46,6 +46,23 @@ private[iron] trait IronCatsInstances extends IronCatsLowPriority, RefinedTypeOp given negLongCommutativeSemigroup: CommutativeSemigroup[Long :| Negative] = commutativeSemigroup[Long, Negative] given negFloatCommutativeSemigroup: CommutativeSemigroup[Float :| Negative] = commutativeSemigroup[Float, Negative] given negDoubleCommutativeSemigroup: CommutativeSemigroup[Double :| Negative] = commutativeSemigroup[Double, Negative] + + private def commutativeMonoid[A, C](using inner: CommutativeMonoid[A], bounds: Bounds[A, C]): CommutativeMonoid[A :| C] = + new CommutativeMonoid[A :| C]: + + override def empty: A :| C = inner.empty.assume[C] + + override def combine(a: A :| C, b: A :| C): A :| C = bounds.shift(inner.combine(a, b)) + + given posIntCommutativeMonoid: CommutativeMonoid[Int :| Positive0] = commutativeMonoid[Int, Positive0] + given posLongCommutativeMonoid: CommutativeMonoid[Long :| Positive0] = commutativeMonoid[Long, Positive0] + given posFloatCommutativeMonoid: CommutativeMonoid[Float :| Positive0] = commutativeMonoid[Float, Positive0] + given posDoubleCommutativeMonoid: CommutativeMonoid[Double :| Positive0] = commutativeMonoid[Double, Positive0] + + given negIntCommutativeMonoid: CommutativeMonoid[Int :| Negative0] = commutativeMonoid[Int, Negative0] + given negLongCommutativeMonoid: CommutativeMonoid[Long :| Negative0] = commutativeMonoid[Long, Negative0] + given negFloatCommutativeMonoid: CommutativeMonoid[Float :| Negative0] = commutativeMonoid[Float, Negative0] + given negDoubleCommutativeMonoid: CommutativeMonoid[Double :| Negative0] = commutativeMonoid[Double, Negative0] /** * Cats' instances for Iron that need to have a lower priority to avoid ambiguous implicits. @@ -81,4 +98,19 @@ private trait RefinedTypeOpsCatsLowPriority: given negFloatAdditiveCommutativeSemigroup: AdditiveCommutativeSemigroup[Float :| Negative] = additiveCommutativeSemigroup[Float, Negative] given negDoubleAdditiveCommutativeSemigroup: AdditiveCommutativeSemigroup[Double :| Negative] = additiveCommutativeSemigroup[Double, Negative] + private def additiveCommutativeMonoid[A, C](using inner: AdditiveCommutativeMonoid[A], bounds: Bounds[A, C]): AdditiveCommutativeMonoid[A :| C] = new: + + override def zero: A :| C = inner.zero.assume[C] + override def plus(x: A :| C, y: A :| C): A :| C = bounds.shift(inner.plus(x, y)) + + given posIntAdditiveCommutativeMonoid: AdditiveCommutativeMonoid[Int :| Positive0] = additiveCommutativeMonoid[Int, Positive0] + given posLongAdditiveCommutativeMonoid: AdditiveCommutativeMonoid[Long :| Positive0] = additiveCommutativeMonoid[Long, Positive0] + given posFloatAdditiveCommutativeMonoid: AdditiveCommutativeMonoid[Float :| Positive0] = additiveCommutativeMonoid[Float, Positive0] + given posDoubleAdditiveCommutativeMonoid: AdditiveCommutativeMonoid[Double :| Positive0] = additiveCommutativeMonoid[Double, Positive0] + + given negIntAdditiveCommutativeMonoid: AdditiveCommutativeMonoid[Int :| Negative0] = additiveCommutativeMonoid[Int, Negative0] + given negLongAdditiveCommutativeMonoid: AdditiveCommutativeMonoid[Long :| Negative0] = additiveCommutativeMonoid[Long, Negative0] + given negFloatAdditiveCommutativeMonoid: AdditiveCommutativeMonoid[Float :| Negative0] = additiveCommutativeMonoid[Float, Negative0] + given negDoubleAdditiveCommutativeMonoid: AdditiveCommutativeMonoid[Double :| Negative0] = additiveCommutativeMonoid[Double, Negative0] + \ No newline at end of file diff --git a/cats/test/src/io/github/iltotore/iron/CatsSuite.scala b/cats/test/src/io/github/iltotore/iron/CatsSuite.scala index dfa92e9..aa73e67 100644 --- a/cats/test/src/io/github/iltotore/iron/CatsSuite.scala +++ b/cats/test/src/io/github/iltotore/iron/CatsSuite.scala @@ -13,7 +13,7 @@ import _root_.cats.data.NonEmptyList import _root_.cats.data.Validated.{Invalid, Valid} import scala.runtime.stdLibPatches.Predef.assert -import algebra.ring.AdditiveCommutativeSemigroup +import algebra.ring.{AdditiveCommutativeMonoid, AdditiveCommutativeSemigroup} object CatsSuite extends TestSuite: @@ -86,6 +86,23 @@ object CatsSuite extends TestSuite: test("pos") - assert(CommutativeSemigroup[Double :| Positive].combine(1, 5) == 6) test("neg") - assert(CommutativeSemigroup[Double :| Negative].combine(-1, -5) == -6) + test("commutativeMonoid"): + test("int"): + test("pos") - assert(CommutativeMonoid[Int :| Positive0].combine(1, 5) == 6) + test("neg") - assert(CommutativeMonoid[Int :| Negative0].combine(-1, -5) == -6) + + test("long"): + test("pos") - assert(CommutativeMonoid[Long :| Positive0].combine(1, 5) == 6) + test("neg") - assert(CommutativeMonoid[Long :| Negative0].combine(-1, -5) == -6) + + test("float"): + test("pos") - assert(CommutativeMonoid[Float :| Positive0].combine(1, 5) == 6) + test("neg") - assert(CommutativeMonoid[Float :| Negative0].combine(-1, -5) == -6) + + test("double"): + test("pos") - assert(CommutativeMonoid[Double :| Positive0].combine(1, 5) == 6) + test("neg") - assert(CommutativeMonoid[Double :| Negative0].combine(-1, -5) == -6) + test("additiveCommutativeSemigroup"): test("int"): test("pos") - assert(AdditiveCommutativeSemigroup[Int :| Positive].plus(1, 5) == 6) @@ -102,6 +119,23 @@ object CatsSuite extends TestSuite: test("double"): test("pos") - assert(AdditiveCommutativeSemigroup[Double :| Positive].plus(1, 5) == 6) test("neg") - assert(AdditiveCommutativeSemigroup[Double :| Negative].plus(-1, -5) == -6) + + test("additiveCommutativeMonoid"): + test("int"): + test("pos") - assert(AdditiveCommutativeMonoid[Int :| Positive0].plus(1, 5) == 6) + test("neg") - assert(AdditiveCommutativeMonoid[Int :| Negative0].plus(-1, -5) == -6) + + test("long"): + test("pos") - assert(AdditiveCommutativeMonoid[Long :| Positive0].plus(1, 5) == 6) + test("neg") - assert(AdditiveCommutativeMonoid[Long :| Negative0].plus(-1, -5) == -6) + + test("float"): + test("pos") - assert(AdditiveCommutativeMonoid[Float :| Positive0].plus(1, 5) == 6) + test("neg") - assert(AdditiveCommutativeMonoid[Float :| Negative0].plus(-1, -5) == -6) + + test("double"): + test("pos") - assert(AdditiveCommutativeMonoid[Double :| Positive0].plus(1, 5) == 6) + test("neg") - assert(AdditiveCommutativeMonoid[Double :| Negative0].plus(-1, -5) == -6) } test("eitherNec"):