diff --git a/core/src/main/scala/cats/data/Xor.scala b/core/src/main/scala/cats/data/Xor.scala index db3aeb0902..232d782fef 100644 --- a/core/src/main/scala/cats/data/Xor.scala +++ b/core/src/main/scala/cats/data/Xor.scala @@ -156,7 +156,13 @@ sealed abstract class XorInstances extends XorInstances1 { def show(f: A Xor B): String = f.show } - implicit def xorInstances[A]: Traverse[A Xor ?] with MonadError[Xor, A ]= + implicit def xorMonoid[A, B](implicit A: Semigroup[A], B: Monoid[B]): Monoid[A Xor B] = + new Monoid[A Xor B] { + def empty: A Xor B = Xor.Right(B.empty) + def combine(x: A Xor B, y: A Xor B): A Xor B = x combine y + } + + implicit def xorInstances[A]: Traverse[A Xor ?] with MonadError[Xor, A ] = new Traverse[A Xor ?] with MonadError[Xor, A] { def traverse[F[_]: Applicative, B, C](fa: A Xor B)(f: B => F[C]): F[A Xor C] = fa.traverse(f) def foldLeft[B, C](fa: A Xor B, c: C)(f: (C, B) => C): C = fa.foldLeft(c)(f) diff --git a/tests/shared/src/test/scala/cats/tests/XorTests.scala b/tests/shared/src/test/scala/cats/tests/XorTests.scala index 5b97946f3b..b209792fd2 100644 --- a/tests/shared/src/test/scala/cats/tests/XorTests.scala +++ b/tests/shared/src/test/scala/cats/tests/XorTests.scala @@ -3,6 +3,7 @@ package tests import cats.data.Xor import cats.data.Xor._ +import cats.laws.discipline.arbitrary.xorArbitrary import cats.laws.discipline.{TraverseTests, MonadErrorTests, SerializableTests} import org.scalacheck.{Arbitrary, Gen} import org.scalacheck.Prop._ @@ -12,6 +13,8 @@ import org.scalacheck.Arbitrary._ import scala.util.Try class XorTests extends CatsSuite { + checkAll("Xor[String, Int]", algebra.laws.GroupLaws[Xor[String, Int]].monoid) + checkAll("Xor[String, Int]", MonadErrorTests[Xor, String].monadError[Int, Int, Int]) checkAll("MonadError[Xor, String]", SerializableTests.serializable(MonadError[Xor, String]))