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 21, 2016
1 parent caf9901 commit 462d3e8
Show file tree
Hide file tree
Showing 6 changed files with 76 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
}
19 changes: 18 additions & 1 deletion core/src/main/scala/cats/syntax/xor.scala
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
package cats
package syntax

import cats.data.Xor
import cats.data.{Xor, XorT}

trait XorSyntax {
implicit def catsSyntaxXorId[A](a: A): XorIdOps[A] = new XorIdOps(a)

implicit def catsSyntaxXorXorT[A, B](axb: A Xor B): XorXorTOps[A, B] = new XorXorTOps(axb)
}

final class XorIdOps[A](val a: A) extends AnyVal {
def left[B]: A Xor B = Xor.Left(a)
def right[B]: B Xor A = Xor.Right(a)
}

final class XorXorTOps[A, B](val axb: A Xor B) {
/**
* Transform this `Xor` into a [[cats.data.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))
}
39 changes: 39 additions & 0 deletions core/src/main/scala/cats/syntax/xort.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package cats
package syntax

import cats.data.XorT

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

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)
}
1 change: 1 addition & 0 deletions 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 Down

0 comments on commit 462d3e8

Please sign in to comment.