Skip to content

Commit

Permalink
Add syntax to create a XorT from an F[A] and from a Xor.
Browse files Browse the repository at this point in the history
  • Loading branch information
peterneyens committed Jun 20, 2016
1 parent caf9901 commit d0d8fe0
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 4 deletions.
13 changes: 13 additions & 0 deletions core/src/main/scala/cats/data/Xor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,19 @@ sealed abstract class Xor[+A, +B] extends Product with Serializable {
def to[F[_], BB >: B](implicit F: Alternative[F]): F[BB] =
fold(_ => F.empty, F.pure)

/**
* Transform this `Xor` into a [[XorT]] while lifting it into the specified Applicative.
*
* {{{
* scala> import cats.implicits._
* scala> val x: Xor[String, Int] = Xor.right(3)
* scala> x.toXorT[Option, String, Int]
* res0: cats.data.XorT[Option, String, Int] = XorT(Some(Right(3)))
* }}}
*/
def toXorT[F[_], L, R](implicit F: Applicative[F], evL: A <:< L, evR: B <:< R): XorT[F, L, R] =
XorT(F.pure(bimap(evL, evR)))

def bimap[C, D](fa: A => C, fb: B => D): C Xor D = this match {
case Xor.Left(a) => Xor.Left(fa(a))
case Xor.Right(b) => Xor.Right(fb(b))
Expand Down
5 changes: 3 additions & 2 deletions core/src/main/scala/cats/syntax/all.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ trait AllSyntax
with ComonadSyntax
with ComposeSyntax
with ContravariantSyntax
with CoproductSyntax
with EitherSyntax
with EqSyntax
with FlatMapSyntax
Expand All @@ -37,7 +38,7 @@ trait AllSyntax
with StrongSyntax
with TransLiftSyntax
with TraverseSyntax
with XorSyntax
with ValidatedSyntax
with CoproductSyntax
with WriterSyntax
with XorSyntax
with XorTSyntax
3 changes: 2 additions & 1 deletion core/src/main/scala/cats/syntax/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ package object syntax {
object strong extends StrongSyntax
object transLift extends TransLiftSyntax
object traverse extends TraverseSyntax
object xor extends XorSyntax
object validated extends ValidatedSyntax
object writer extends WriterSyntax
object xor extends XorSyntax
object xort extends XorTSyntax
// scalastyle:on number.of.types
}
57 changes: 57 additions & 0 deletions core/src/main/scala/cats/syntax/xort.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package cats
package syntax

import cats.data.{Xor, XorT}

trait XorTSyntax extends XorTSyntax1 {
implicit def catsSyntaxXorT[F[_]: Functor, A](fa: F[A]): XorTOps[F, A] = new XorTOps(fa)

implicit def catsSyntaxXorTXor[A, B](axb: A Xor B): XorTXorOps[A, B] = new XorTXorOps(axb)
}

trait XorTSyntax1 {
implicit def catsSyntaxUXorT[FA](fa: FA)(implicit U: Unapply[Functor, FA]): XorTOps[U.M, U.A] =
new XorTOps[U.M, U.A](U.subst(fa))(U.TC)
}

final class XorTOps[F[_]: Functor, A](val fa: F[A]) {
/**
* Lift this `F[A]` into a `XorT[F, A, R]`.
*
* {{{
* scala> import cats.implicits._
* scala> val oa: Option[String] = Some("boo")
* scala> oa.leftXorT[Int]
* res0: cats.data.XorT[Option,String,Int] = XorT(Some(Left(boo)))
* }}}
*/
def leftXorT[R]: XorT[F, A, R] = XorT.left(fa)

/**
* Lift this `F[A]` into a `XorT[F, L, A]`.
*
* {{{
* scala> import cats.implicits._
* scala> val oa: Option[Int] = Some(1)
* scala> oa.rightXorT[String]
* res0: cats.data.XorT[Option,String,Int] = XorT(Some(Right(1)))
* }}}
*/
def rightXorT[L]: XorT[F, L, A] = XorT.right(fa)
}


final class XorTXorOps[A, B](val axb: A Xor B) {
/**
* Transform this `Xor` into a [[XorT]] while lifting it into the specified Applicative.
*
* {{{
* scala> import cats.implicits._
* scala> import cats.data.Xor
* scala> val x: Xor[String, Int] = Xor.right(3)
* scala> x.toXorT2[Option]
* res0: cats.data.XorT[Option, String, Int] = XorT(Some(Right(3)))
* }}}
*/
def toXorT2[F[_]](implicit F: Applicative[F]): XorT[F, A, B] = XorT(F.pure(axb))
}
3 changes: 2 additions & 1 deletion tests/src/test/scala/cats/tests/XorTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ class XorTests extends CatsSuite {
x.isLeft should === (x.toList.isEmpty)
x.isLeft should === (x.toValidated.isInvalid)
x.isLeft should === (x.toValidatedNel.isInvalid)
Option(x.isLeft) should === (x.toXorT[Option, Int, String].isLeft)
}
}

Expand All @@ -228,7 +229,7 @@ class XorTests extends CatsSuite {
}
}

test("combine is right iff both operands are right") {
test("combine is right if both operands are right") {
forAll { (x: Int Xor String, y: Int Xor String) =>
x.combine(y).isRight should === (x.isRight && y.isRight)
}
Expand Down

0 comments on commit d0d8fe0

Please sign in to comment.