Skip to content

Commit

Permalink
Merge pull request #644 from ceedubs/xort-traverse
Browse files Browse the repository at this point in the history
Add Traverse and Foldable instances for XorT
  • Loading branch information
stew committed Nov 15, 2015
2 parents 2f853d5 + aa91f29 commit b2b967b
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 3 deletions.
24 changes: 24 additions & 0 deletions core/src/main/scala/cats/data/XorT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ private[data] abstract class XorTInstances extends XorTInstances1 {
}
}

implicit def xorTTraverse[F[_], L](implicit F: Traverse[F]): Traverse[XorT[F, L, ?]] =
new XorTTraverse[F, L] {
val F0: Traverse[F] = F
}
}

private[data] abstract class XorTInstances1 extends XorTInstances2 {
Expand All @@ -191,6 +195,11 @@ private[data] abstract class XorTInstances1 extends XorTInstances2 {
def empty[A]: XorT[F, L, A] = XorT.left(F.pure(L.empty))(F)
}
}

implicit def xorTFoldable[F[_], L](implicit F: Foldable[F]): Foldable[XorT[F, L, ?]] =
new XorTFoldable[F, L] {
val F0: Foldable[F] = F
}
}

private[data] abstract class XorTInstances2 extends XorTInstances3 {
Expand Down Expand Up @@ -264,4 +273,19 @@ private[data] trait XorTMonadCombine[F[_], L] extends MonadCombine[XorT[F, L, ?]
implicit val L: Monoid[L]
}

private[data] sealed trait XorTFoldable[F[_], L] extends Foldable[XorT[F, L, ?]] {
implicit def F0: Foldable[F]

def foldLeft[A, B](fa: XorT[F, L, A], b: B)(f: (B, A) => B): B =
fa.foldLeft(b)(f)

def foldRight[A, B](fa: XorT[F, L, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
fa.foldRight(lb)(f)
}

private[data] sealed trait XorTTraverse[F[_], L] extends Traverse[XorT[F, L, ?]] with XorTFoldable[F, L] {
override implicit def F0: Traverse[F]

override def traverse[G[_]: Applicative, A, B](fa: XorT[F, L, A])(f: A => G[B]): G[XorT[F, L, B]] =
fa traverse f
}
26 changes: 23 additions & 3 deletions tests/src/test/scala/cats/tests/XorTTests.scala
Original file line number Diff line number Diff line change
@@ -1,18 +1,38 @@
package cats
package tests

import cats.functor.Bifunctor
import cats.data.{Xor, XorT}
import cats.laws.discipline.{BifunctorTests, MonadErrorTests, MonoidKTests, SerializableTests}
import cats.laws.discipline.{BifunctorTests, FoldableTests, FunctorTests, MonadErrorTests, MonoidKTests, SerializableTests, TraverseTests}
import cats.laws.discipline.arbitrary._


class XorTTests extends CatsSuite {
implicit val eq0 = XorT.xorTEq[List, String, String Xor Int]
implicit val eq1 = XorT.xorTEq[XorT[List, String, ?], String, Int](eq0)
checkAll("XorT[List, String, Int]", MonadErrorTests[XorT[List, String, ?], String].monadError[Int, Int, Int])
checkAll("XorT[List, String, Int]", MonoidKTests[XorT[List, String, ?]].monoidK[Int])
checkAll("MonadError[XorT[List, ?, ?]]", SerializableTests.serializable(MonadError[XorT[List, String, ?], String]))
checkAll("XorT[List, String, Int]", MonoidKTests[XorT[List, String, ?]].monoidK[Int])
checkAll("MonoidK[XorT[List, String, ?]]", SerializableTests.serializable(MonoidK[XorT[List, String, ?]]))
checkAll("XorT[List, ?, ?]", BifunctorTests[XorT[List, ?, ?]].bifunctor[Int, Int, Int, String, String, String])
checkAll("Bifunctor[XorT[List, ?, ?]]", SerializableTests.serializable(Bifunctor[XorT[List, ?, ?]]))
checkAll("XorT[List, Int, ?]", TraverseTests[XorT[List, Int, ?]].foldable[Int, Int])
checkAll("Traverse[XorT[List, Int, ?]]", SerializableTests.serializable(Traverse[XorT[List, Int, ?]]))

{
implicit val F = ListWrapper.foldable
checkAll("XorT[ListWrapper, Int, ?]", FoldableTests[XorT[ListWrapper, Int, ?]].foldable[Int, Int])
checkAll("Foldable[XorT[ListWrapper, Int, ?]]", SerializableTests.serializable(Foldable[XorT[ListWrapper, Int, ?]]))
}

{
implicit val F = ListWrapper.functor
checkAll("XorT[ListWrapper, Int, ?]", FunctorTests[XorT[ListWrapper, Int, ?]].functor[Int, Int, Int])
checkAll("Functor[XorT[ListWrapper, Int, ?]]", SerializableTests.serializable(Functor[XorT[ListWrapper, Int, ?]]))
}

// make sure that the Monad and Traverse instances don't result in ambiguous
// Functor instances
Functor[XorT[List, Int, ?]]

test("toValidated") {
forAll { (xort: XorT[List, String, Int]) =>
Expand Down

0 comments on commit b2b967b

Please sign in to comment.