Skip to content

Commit aa0006d

Browse files
authored
Merge pull request #1306 from adelbertc/partial-revert-either
Partial revert of #1289
2 parents 6e12494 + 1867956 commit aa0006d

36 files changed

+155
-142
lines changed

core/src/main/scala/cats/ApplicativeError.scala

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package cats
22

3-
import cats.data.EitherT
3+
import cats.data.{Xor, XorT}
44
import scala.util.{ Failure, Success, Try }
55
import scala.util.control.NonFatal
66

@@ -37,21 +37,21 @@ trait ApplicativeError[F[_], E] extends Applicative[F] {
3737
def handleError[A](fa: F[A])(f: E => A): F[A] = handleErrorWith(fa)(f andThen pure)
3838

3939
/**
40-
* Handle errors by turning them into [[scala.util.Either]] values.
40+
* Handle errors by turning them into [[cats.data.Xor]] values.
4141
*
4242
* If there is no error, then an `scala.util.Right` value will be returned instead.
4343
*
4444
* All non-fatal errors should be handled by this method.
4545
*/
46-
def attempt[A](fa: F[A]): F[Either[E, A]] = handleErrorWith(
47-
map(fa)(Right(_): Either[E, A])
48-
)(e => pure(Left(e)))
46+
def attempt[A](fa: F[A]): F[Xor[E, A]] = handleErrorWith(
47+
map(fa)(Xor.Right(_): Xor[E, A])
48+
)(e => pure(Xor.Left(e)))
4949

5050
/**
51-
* Similar to [[attempt]], but wraps the result in a [[cats.data.EitherT]] for
51+
* Similar to [[attempt]], but wraps the result in a [[cats.data.XorT]] for
5252
* convenience.
5353
*/
54-
def attemptT[A](fa: F[A]): EitherT[F, E, A] = EitherT(attempt(fa))
54+
def attemptT[A](fa: F[A]): XorT[F, E, A] = XorT(attempt(fa))
5555

5656
/**
5757
* Recover from certain errors by mapping them to an `A` value.

core/src/main/scala/cats/Foldable.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ import simulacrum.typeclass
207207
/**
208208
* Behaves like traverse_, but uses [[Unapply]] to find the
209209
* [[Applicative]] instance for `G` - used when `G` is a
210-
* type constructor with two or more parameters such as [[scala.util.Either]]
210+
* type constructor with two or more parameters such as `scala.util.Either`
211211
*
212212
* {{{
213213
* scala> import cats.implicits._
@@ -251,7 +251,7 @@ import simulacrum.typeclass
251251
/**
252252
* Behaves like sequence_, but uses [[Unapply]] to find the
253253
* [[Applicative]] instance for `G` - used when `G` is a
254-
* type constructor with two or more parameters such as [[scala.util.Either]]
254+
* type constructor with two or more parameters such as `scala.util.Either`
255255
*
256256
* {{{
257257
* scala> import cats.implicits._
+11-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cats
22
package arrow
33

4+
import cats.data.Xor
45
import simulacrum.typeclass
56

67
@typeclass trait Choice[F[_, _]] extends Category[F] {
@@ -11,35 +12,37 @@ import simulacrum.typeclass
1112
*
1213
* Example:
1314
* {{{
15+
* scala> import cats.data.Xor
1416
* scala> import cats.implicits._
1517
* scala> val b: Boolean => String = _ + " is a boolean"
1618
* scala> val i: Int => String = _ + " is an integer"
17-
* scala> val f: (Either[Boolean, Int]) => String = Choice[Function1].choice(b, i)
19+
* scala> val f: Xor[Boolean, Int] => String = Choice[Function1].choice(b, i)
1820
*
19-
* scala> f(Right(3))
21+
* scala> f(Xor.Right(3))
2022
* res0: String = 3 is an integer
2123
*
22-
* scala> f(Left(false))
24+
* scala> f(Xor.Left(false))
2325
* res0: String = false is a boolean
2426
* }}}
2527
*/
26-
def choice[A, B, C](f: F[A, C], g: F[B, C]): F[Either[A, B], C]
28+
def choice[A, B, C](f: F[A, C], g: F[B, C]): F[Xor[A, B], C]
2729

2830
/**
2931
* An `F` that, given a source `A` on either the right or left side, will
3032
* return that same `A` object.
3133
*
3234
* Example:
3335
* {{{
36+
* scala> import cats.data.Xor
3437
* scala> import cats.implicits._
35-
* scala> val f: (Either[Int, Int]) => Int = Choice[Function1].codiagonal[Int]
38+
* scala> val f: (Xor[Int, Int]) => Int = Choice[Function1].codiagonal[Int]
3639
*
37-
* scala> f(Right(3))
40+
* scala> f(Xor.Right(3))
3841
* res0: Int = 3
3942
*
40-
* scala> f(Left(3))
43+
* scala> f(Xor.Left(3))
4144
* res1: Int = 3
4245
* }}}
4346
*/
44-
def codiagonal[A]: F[Either[A, A], A] = choice(id, id)
47+
def codiagonal[A]: F[Xor[A, A], A] = choice(id, id)
4548
}

core/src/main/scala/cats/arrow/FunctionK.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package cats
22
package arrow
33

4-
import cats.data. Coproduct
4+
import cats.data.{Coproduct, Xor}
55

66
trait FunctionK[F[_], G[_]] extends Serializable { self =>
77
def apply[A](fa: F[A]): G[A]
@@ -17,8 +17,8 @@ trait FunctionK[F[_], G[_]] extends Serializable { self =>
1717
def or[H[_]](h: FunctionK[H, G]): FunctionK[Coproduct[F, H, ?], G] =
1818
new FunctionK[Coproduct[F, H, ?], G] {
1919
def apply[A](fa: Coproduct[F, H, A]): G[A] = fa.run match {
20-
case Left(ff) => self(ff)
21-
case Right(gg) => h(gg)
20+
case Xor.Left(ff) => self(ff)
21+
case Xor.Right(gg) => h(gg)
2222
}
2323
}
2424
}

core/src/main/scala/cats/data/Coproduct.scala

+8-9
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@ package data
33

44
import cats.arrow.FunctionK
55
import cats.functor.Contravariant
6-
import cats.syntax.either._
76

8-
/** `F` on the left and `G` on the right of [[scala.util.Either]].
7+
/** `F` on the left and `G` on the right of [[cats.data.Xor]].
98
*
10-
* @param run The underlying [[scala.util.Either]].
9+
* @param run The underlying [[cats.data.Xor]].
1110
*/
12-
final case class Coproduct[F[_], G[_], A](run: Either[F[A], G[A]]) {
11+
final case class Coproduct[F[_], G[_], A](run: Xor[F[A], G[A]]) {
1312

1413
import Coproduct._
1514

@@ -87,17 +86,17 @@ final case class Coproduct[F[_], G[_], A](run: Either[F[A], G[A]]) {
8786
object Coproduct extends CoproductInstances {
8887

8988
def leftc[F[_], G[_], A](x: F[A]): Coproduct[F, G, A] =
90-
Coproduct(Left(x))
89+
Coproduct(Xor.Left(x))
9190

9291
def rightc[F[_], G[_], A](x: G[A]): Coproduct[F, G, A] =
93-
Coproduct(Right(x))
92+
Coproduct(Xor.Right(x))
9493

9594
final class CoproductLeft[G[_]] private[Coproduct] {
96-
def apply[F[_], A](fa: F[A]): Coproduct[F, G, A] = Coproduct(Left(fa))
95+
def apply[F[_], A](fa: F[A]): Coproduct[F, G, A] = Coproduct(Xor.Left(fa))
9796
}
9897

9998
final class CoproductRight[F[_]] private[Coproduct] {
100-
def apply[G[_], A](ga: G[A]): Coproduct[F, G, A] = Coproduct(Right(ga))
99+
def apply[G[_], A](ga: G[A]): Coproduct[F, G, A] = Coproduct(Xor.Right(ga))
101100
}
102101

103102
def left[G[_]]: CoproductLeft[G] = new CoproductLeft[G]
@@ -107,7 +106,7 @@ object Coproduct extends CoproductInstances {
107106

108107
private[data] sealed abstract class CoproductInstances3 {
109108

110-
implicit def catsDataEqForCoproduct[F[_], G[_], A](implicit E: Eq[Either[F[A], G[A]]]): Eq[Coproduct[F, G, A]] =
109+
implicit def catsDataEqForCoproduct[F[_], G[_], A](implicit E: Eq[Xor[F[A], G[A]]]): Eq[Coproduct[F, G, A]] =
111110
Eq.by(_.run)
112111

113112
implicit def catsDataFunctorForCoproduct[F[_], G[_]](implicit F0: Functor[F], G0: Functor[G]): Functor[Coproduct[F, G, ?]] =

core/src/main/scala/cats/data/EitherT.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ private[data] trait EitherTMonadError[F[_], L] extends MonadError[EitherT[F, L,
393393
case r @ Right(_) => F.pure(r)
394394
})
395395
def raiseError[A](e: L): EitherT[F, L, A] = EitherT.left(F.pure(e))
396-
override def attempt[A](fla: EitherT[F, L, A]): EitherT[F, L, Either[L, A]] = EitherT.right(fla.value)
396+
override def attempt[A](fla: EitherT[F, L, A]): EitherT[F, L, Xor[L, A]] = EitherT.right(F.map(fla.value)(_.toXor))
397397
override def recover[A](fla: EitherT[F, L, A])(pf: PartialFunction[L, A]): EitherT[F, L, A] =
398398
fla.recover(pf)
399399
override def recoverWith[A](fla: EitherT[F, L, A])(pf: PartialFunction[L, EitherT[F, L, A]]): EitherT[F, L, A] =

core/src/main/scala/cats/data/Ior.scala

+6-6
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ import scala.annotation.tailrec
1111
* - `[[Ior.Right Right]][B]`
1212
* - `[[Ior.Both Both]][A, B]`
1313
*
14-
* `A [[Ior]] B` is similar to `Either[A, B]`, except that it can represent the simultaneous presence of
14+
* `A [[Ior]] B` is similar to `Xor[A, B]`, except that it can represent the simultaneous presence of
1515
* an `A` and a `B`. It is right-biased so methods such as `map` and `flatMap` operate on the
1616
* `B` value. Some methods, like `flatMap`, handle the presence of two [[Ior.Both Both]] values using a
17-
* `[[Semigroup]][A]`, while other methods, like [[toEither]], ignore the `A` value in a [[Ior.Both Both]].
17+
* `[[Semigroup]][A]`, while other methods, like [[toXor]], ignore the `A` value in a [[Ior.Both Both]].
1818
*
19-
* `A [[Ior]] B` is isomorphic to `Either[Either[A, B], (A, B)]`, but provides methods biased toward `B`
19+
* `A [[Ior]] B` is isomorphic to `Xor[Xor[A, B], (A, B)]`, but provides methods biased toward `B`
2020
* values, regardless of whether the `B` values appear in a [[Ior.Right Right]] or a [[Ior.Both Both]].
21-
* The isomorphic [[scala.util.Either]] form can be accessed via the [[unwrap]] method.
21+
* The isomorphic [[cats.data.Xor]] form can be accessed via the [[unwrap]] method.
2222
*/
2323
sealed abstract class Ior[+A, +B] extends Product with Serializable {
2424

@@ -36,10 +36,10 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
3636
final def right: Option[B] = fold(_ => None, b => Some(b), (_, b) => Some(b))
3737
final def onlyLeft: Option[A] = fold(a => Some(a), _ => None, (_, _) => None)
3838
final def onlyRight: Option[B] = fold(_ => None, b => Some(b), (_, _) => None)
39-
final def onlyLeftOrRight: Option[Either[A, B]] = fold(a => Some(Left(a)), b => Some(Right(b)), (_, _) => None)
39+
final def onlyLeftOrRight: Option[Xor[A, B]] = fold(a => Some(Xor.Left(a)), b => Some(Xor.Right(b)), (_, _) => None)
4040
final def onlyBoth: Option[(A, B)] = fold(_ => None, _ => None, (a, b) => Some((a, b)))
4141
final def pad: (Option[A], Option[B]) = fold(a => (Some(a), None), b => (None, Some(b)), (a, b) => (Some(a), Some(b)))
42-
final def unwrap: Either[Either[A, B], (A, B)] = fold(a => Left(Left(a)), b => Left(Right(b)), (a, b) => Right((a, b)))
42+
final def unwrap: Xor[Xor[A, B], (A, B)] = fold(a => Xor.Left(Xor.Left(a)), b => Xor.Left(Xor.Right(b)), (a, b) => Xor.Right((a, b)))
4343

4444
final def toXor: A Xor B = fold(Xor.left, Xor.right, (_, b) => Xor.right(b))
4545
final def toEither: Either[A, B] = fold(Left(_), Right(_), (_, b) => Right(b))

core/src/main/scala/cats/data/Kleisli.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ private[data] sealed abstract class KleisliInstances extends KleisliInstances0 {
101101
new Choice[Kleisli[F, ?, ?]] {
102102
def id[A]: Kleisli[F, A, A] = Kleisli(ev.pure(_))
103103

104-
def choice[A, B, C](f: Kleisli[F, A, C], g: Kleisli[F, B, C]): Kleisli[F, Either[A, B], C] =
104+
def choice[A, B, C](f: Kleisli[F, A, C], g: Kleisli[F, B, C]): Kleisli[F, Xor[A, B], C] =
105105
Kleisli(_.fold(f.run, g.run))
106106

107107
def compose[A, B, C](f: Kleisli[F, B, C], g: Kleisli[F, A, B]): Kleisli[F, A, C] =

core/src/main/scala/cats/data/OptionT.scala

+4-4
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,11 @@ final case class OptionT[F[_], A](value: F[Option[A]]) {
8686
case None => default
8787
})
8888

89-
def toRight[L](left: => L)(implicit F: Functor[F]): EitherT[F, L, A] =
90-
EitherT(cata(Left(left), Right.apply))
89+
def toRight[L](left: => L)(implicit F: Functor[F]): XorT[F, L, A] =
90+
XorT(cata(Xor.Left(left), Xor.Right.apply))
9191

92-
def toLeft[R](right: => R)(implicit F: Functor[F]): EitherT[F, A, R] =
93-
EitherT(cata(Right(right), Left.apply))
92+
def toLeft[R](right: => R)(implicit F: Functor[F]): XorT[F, A, R] =
93+
XorT(cata(Xor.Right(right), Xor.Left.apply))
9494

9595
def show(implicit F: Show[F[Option[A]]]): String = F.show(value)
9696

core/src/main/scala/cats/data/Validated.scala

+9-4
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,11 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
8080
def toXor: Xor[E, A] = fold(Xor.Left.apply, Xor.Right.apply)
8181

8282
/**
83-
* Convert to an Either, apply a function, convert back. This is handy
84-
* when you want to use the Monadic properties of the Either type.
83+
* Convert to an Xor, apply a function, convert back. This is handy
84+
* when you want to use the Monadic properties of the Xor type.
8585
*/
86-
def withEither[EE, B](f: Either[E, A] => Either[EE, B]): Validated[EE, B] =
87-
Validated.fromEither(f(toEither))
86+
def withXor[EE, B](f: Xor[E, A] => Xor[EE, B]): Validated[EE, B] =
87+
Validated.fromXor(f(toXor))
8888

8989
/**
9090
* Validated is a [[functor.Bifunctor]], this method applies one of the
@@ -391,6 +391,11 @@ trait ValidatedFunctions {
391391
*/
392392
def fromEither[A, B](e: Either[A, B]): Validated[A, B] = e.fold(invalid, valid)
393393

394+
/**
395+
* Converts an `Xor[A, B]` to an `Validated[A, B]`.
396+
*/
397+
def fromXor[A, B](e: Xor[A, B]): Validated[A, B] = e.fold(invalid, valid)
398+
394399
/**
395400
* Converts an `Option[B]` to an `Validated[A, B]`, where the provided `ifNone` values is returned on
396401
* the invalid of the `Validated` when the specified `Option` is `None`.

core/src/main/scala/cats/data/Xor.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ private[data] sealed abstract class XorInstances extends XorInstances1 {
278278
override def map[B, C](fa: A Xor B)(f: B => C): A Xor C = fa.map(f)
279279
override def map2Eval[B, C, Z](fb: A Xor B, fc: Eval[A Xor C])(f: (B, C) => Z): Eval[A Xor Z] =
280280
fb.map2Eval(fc)(f)
281-
override def attempt[B](fab: A Xor B): A Xor (Either[A, B]) = Xor.right(fab.toEither)
281+
override def attempt[B](fab: A Xor B): A Xor (Xor[A, B]) = Xor.right(fab)
282282
override def recover[B](fab: A Xor B)(pf: PartialFunction[A, B]): A Xor B =
283283
fab recover pf
284284
override def recoverWith[B](fab: A Xor B)(pf: PartialFunction[A, A Xor B]): A Xor B =

core/src/main/scala/cats/data/XorT.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ private[data] trait XorTMonadError[F[_], L] extends MonadError[XorT[F, L, ?], L]
403403
case r @ Xor.Right(_) => F.pure(r)
404404
})
405405
def raiseError[A](e: L): XorT[F, L, A] = XorT.left(F.pure(e))
406-
override def attempt[A](fla: XorT[F, L, A]): XorT[F, L, Either[L, A]] = XorT.right(fla.toEither)
406+
override def attempt[A](fla: XorT[F, L, A]): XorT[F, L, Xor[L, A]] = XorT.right(fla.value)
407407
override def recover[A](fla: XorT[F, L, A])(pf: PartialFunction[L, A]): XorT[F, L, A] =
408408
fla.recover(pf)
409409
override def recoverWith[A](fla: XorT[F, L, A])(pf: PartialFunction[L, XorT[F, L, A]]): XorT[F, L, A] =

core/src/main/scala/cats/instances/either.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cats
22
package instances
33

4+
import cats.data.Xor
45
import cats.syntax.EitherUtil
56
import cats.syntax.either._
67
import scala.annotation.tailrec
@@ -71,7 +72,7 @@ trait EitherInstances extends EitherInstances1 {
7172
def foldRight[B, C](fa: Either[A, B], lc: Eval[C])(f: (B, Eval[C]) => Eval[C]): Eval[C] =
7273
fa.fold(_ => lc, b => f(b, lc))
7374

74-
override def attempt[B](fab: Either[A, B]): Either[A, Either[A, B]] = Right(fab)
75+
override def attempt[B](fab: Either[A, B]): Either[A, Xor[A, B]] = Right(fab.toXor)
7576
override def recover[B](fab: Either[A, B])(pf: PartialFunction[A, B]): Either[A, B] =
7677
fab recover pf
7778
override def recoverWith[B](fab: Either[A, B])(pf: PartialFunction[A, Either[A, B]]): Either[A, B] =

core/src/main/scala/cats/instances/function.scala

+4-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cats
22
package instances
33

44
import cats.arrow.{Arrow, Choice}
5+
import cats.data.Xor
56
import cats.functor.Contravariant
67
import annotation.tailrec
78

@@ -70,10 +71,10 @@ private[instances] sealed trait Function1Instances extends Function1Instances0 {
7071

7172
implicit val catsStdInstancesForFunction1: Choice[Function1] with Arrow[Function1] =
7273
new Choice[Function1] with Arrow[Function1] {
73-
def choice[A, B, C](f: A => C, g: B => C): Either[A, B] => C =
74+
def choice[A, B, C](f: A => C, g: B => C): Xor[A, B] => C =
7475
_ match {
75-
case Left(a) => f(a)
76-
case Right(b) => g(b)
76+
case Xor.Left(a) => f(a)
77+
case Xor.Right(b) => g(b)
7778
}
7879

7980
def lift[A, B](f: A => B): A => B = f

core/src/main/scala/cats/instances/future.scala

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cats
22
package instances
33

4+
import cats.data.Xor
45
import scala.util.control.NonFatal
56
import scala.concurrent.{ExecutionContext, Future}
67

@@ -27,8 +28,8 @@ trait FutureInstances extends FutureInstances1 {
2728
def raiseError[A](e: Throwable): Future[A] = Future.failed(e)
2829
override def handleError[A](fea: Future[A])(f: Throwable => A): Future[A] = fea.recover { case t => f(t) }
2930

30-
override def attempt[A](fa: Future[A]): Future[Either[Throwable, A]] =
31-
(fa.map(a => Right[Throwable, A](a))) recover { case NonFatal(t) => Left(t) }
31+
override def attempt[A](fa: Future[A]): Future[Xor[Throwable, A]] =
32+
(fa.map(a => Xor.Right(a))) recover { case NonFatal(t) => Xor.Left(t) }
3233

3334
override def recover[A](fa: Future[A])(pf: PartialFunction[Throwable, A]): Future[A] = fa.recover(pf)
3435

core/src/main/scala/cats/instances/try.scala

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package instances
33

44
import TryInstances.castFailure
55

6+
import cats.data.Xor
67
import scala.util.control.NonFatal
78
import scala.util.{Failure, Success, Try}
89
import scala.annotation.tailrec
@@ -66,8 +67,8 @@ trait TryInstances extends TryInstances1 {
6667
override def handleError[A](ta: Try[A])(f: Throwable => A): Try[A] =
6768
ta.recover { case t => f(t) }
6869

69-
override def attempt[A](ta: Try[A]): Try[Either[Throwable, A]] =
70-
(ta.map(a => Right[Throwable, A](a))) recover { case NonFatal(t) => Left(t) }
70+
override def attempt[A](ta: Try[A]): Try[Xor[Throwable, A]] =
71+
(ta.map(a => Xor.Right(a))) recover { case NonFatal(t) => Xor.Left(t) }
7172

7273
override def recover[A](ta: Try[A])(pf: PartialFunction[Throwable, A]): Try[A] =
7374
ta.recover(pf)

core/src/main/scala/cats/syntax/applicativeError.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package cats
22
package syntax
33

4-
import cats.data.EitherT
4+
import cats.data.{Xor, XorT}
55

66
trait ApplicativeErrorSyntax {
77
implicit def catsSyntaxApplicativeErrorId[E](e: E): ApplicativeErrorIdOps[E] =
@@ -24,10 +24,10 @@ final class ApplicativeErrorOps[F[_], E, A](fa: F[A])(implicit F: ApplicativeErr
2424
def handleErrorWith(f: E => F[A]): F[A] =
2525
F.handleErrorWith(fa)(f)
2626

27-
def attempt: F[Either[E, A]] =
27+
def attempt: F[Xor[E, A]] =
2828
F.attempt(fa)
2929

30-
def attemptT: EitherT[F, E, A] =
30+
def attemptT: XorT[F, E, A] =
3131
F.attemptT(fa)
3232

3333
def recover(pf: PartialFunction[E, A]): F[A] =

0 commit comments

Comments
 (0)