Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Roll-back #1301 and #1289 to allow 0.7.0 release. #1305

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions core/src/main/scala/cats/ApplicativeError.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package cats

import cats.data.EitherT
import cats.data.{Xor, XorT}
import scala.util.{ Failure, Success, Try }
import scala.util.control.NonFatal

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

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

/**
* Similar to [[attempt]], but wraps the result in a [[cats.data.EitherT]] for
* Similar to [[attempt]], but wraps the result in a [[cats.data.XorT]] for
* convenience.
*/
def attemptT[A](fa: F[A]): EitherT[F, E, A] = EitherT(attempt(fa))
def attemptT[A](fa: F[A]): XorT[F, E, A] = XorT(attempt(fa))

/**
* Recover from certain errors by mapping them to an `A` value.
Expand Down
17 changes: 9 additions & 8 deletions core/src/main/scala/cats/Bitraverse.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,24 @@ import simulacrum.typeclass
*
* Example:
* {{{
* scala> import cats.data.Xor
* scala> import cats.implicits._
*
* scala> val rightSome: Either[Option[String], Option[Int]] = Either.right(Some(3))
* scala> val rightSome: Option[String] Xor Option[Int] = Xor.right(Some(3))
* scala> rightSome.bisequence
* res0: Option[Either[String, Int]] = Some(Right(3))
* res0: Option[String Xor Int] = Some(Right(3))
*
* scala> val rightNone: Either[Option[String], Option[Int]] = Either.right(None)
* scala> val rightNone: Option[String] Xor Option[Int] = Xor.right(None)
* scala> rightNone.bisequence
* res1: Option[Either[String, Int]] = None
* res1: Option[String Xor Int] = None
*
* scala> val leftSome: Either[Option[String], Option[Int]] = Either.left(Some("foo"))
* scala> val leftSome: Option[String] Xor Option[Int] = Xor.left(Some("foo"))
* scala> leftSome.bisequence
* res2: Option[Either[String, Int]] = Some(Left(foo))
* res2: Option[String Xor Int] = Some(Left(foo))
*
* scala> val leftNone: Either[Option[String], Option[Int]] = Either.left(None)
* scala> val leftNone: Option[String] Xor Option[Int] = Xor.left(None)
* scala> leftNone.bisequence
* res3: Option[Either[String, Int]] = None
* res3: Option[String Xor Int] = None
* }}}
*/
def bisequence[G[_]: Applicative, A, B](fab: F[G[A], G[B]]): G[F[A, B]] =
Expand Down
7 changes: 6 additions & 1 deletion core/src/main/scala/cats/Eval.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cats

import scala.annotation.tailrec
import cats.data.Xor
import cats.syntax.all._

/**
Expand Down Expand Up @@ -301,7 +302,11 @@ private[cats] trait EvalInstances extends EvalInstances0 {
def flatMap[A, B](fa: Eval[A])(f: A => Eval[B]): Eval[B] = fa.flatMap(f)
def extract[A](la: Eval[A]): A = la.value
def coflatMap[A, B](fa: Eval[A])(f: Eval[A] => B): Eval[B] = Later(f(fa))
def tailRecM[A, B](a: A)(f: A => Eval[Either[A, B]]): Eval[B] = defaultTailRecM(a)(f)
def tailRecM[A, B](a: A)(f: A => Eval[Xor[A, B]]): Eval[B] =
f(a).flatMap(_ match {
case Xor.Left(a1) => tailRecM(a1)(f) // recursion OK here, since flatMap is lazy
case Xor.Right(b) => Eval.now(b)
})
}

implicit def catsOrderForEval[A: Order]: Order[Eval[A]] =
Expand Down
6 changes: 4 additions & 2 deletions core/src/main/scala/cats/FlatMap.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package cats

import simulacrum.typeclass

import cats.data.Xor

/**
* FlatMap type class gives us flatMap, which allows us to have a value
* in a context (F[A]) and then feed that into a function that takes
Expand Down Expand Up @@ -92,7 +94,7 @@ import simulacrum.typeclass
flatMap(fa)(if (_) ifTrue else ifFalse)

/**
* Keeps calling `f` until a `scala.util.Right[B]` is returned.
* Keeps calling `f` until a `Right[B]` is returned.
*
* Based on Phil Freeman's
* [[http://functorial.com/stack-safety-for-free/index.pdf Stack Safety for Free]].
Expand All @@ -105,5 +107,5 @@ import simulacrum.typeclass
* using recursive flatMap. Such an implementation will only be stack safe if
* the Monad is trampolined.
*/
def tailRecM[A, B](a: A)(f: A => F[Either[A, B]]): F[B]
def tailRecM[A, B](a: A)(f: A => F[Xor[A, B]]): F[B]
}
27 changes: 15 additions & 12 deletions core/src/main/scala/cats/Foldable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,9 @@ import simulacrum.typeclass
* For example:
*
* {{{
* scala> import cats.data.Xor
* scala> import cats.implicits._
* scala> def parseInt(s: String): Option[Int] = Either.catchOnly[NumberFormatException](s.toInt).toOption
* scala> def parseInt(s: String): Option[Int] = Xor.catchOnly[NumberFormatException](s.toInt).toOption
* scala> val F = Foldable[List]
* scala> F.traverse_(List("333", "444"))(parseInt)
* res0: Option[Unit] = Some(())
Expand All @@ -207,18 +208,19 @@ import simulacrum.typeclass
/**
* Behaves like traverse_, but uses [[Unapply]] to find the
* [[Applicative]] instance for `G` - used when `G` is a
* type constructor with two or more parameters such as [[scala.util.Either]]
* type constructor with two or more parameters such as [[cats.data.Xor]]
*
* {{{
* scala> import cats.data.Xor
* scala> import cats.implicits._
* scala> def parseInt(s: String): Either[String, Int] =
* | try { Right(s.toInt) }
* | catch { case _: NumberFormatException => Left("boo") }
* scala> def parseInt(s: String): Xor[String, Int] =
* | try { Xor.Right(s.toInt) }
* | catch { case _: NumberFormatException => Xor.Left("boo") }
* scala> val F = Foldable[List]
* scala> F.traverseU_(List("333", "444"))(parseInt)
* res0: Either[String, Unit] = Right(())
* res0: Xor[String, Unit] = Right(())
* scala> F.traverseU_(List("333", "zzz"))(parseInt)
* res1: Either[String, Unit] = Left(boo)
* res1: Xor[String, Unit] = Left(boo)
* }}}
*
* Note that using `traverse_` instead of `traverseU_` would not compile without
Expand Down Expand Up @@ -251,15 +253,16 @@ import simulacrum.typeclass
/**
* Behaves like sequence_, but uses [[Unapply]] to find the
* [[Applicative]] instance for `G` - used when `G` is a
* type constructor with two or more parameters such as [[scala.util.Either]]
* type constructor with two or more parameters such as [[cats.data.Xor]]
*
* {{{
* scala> import cats.data.Xor
* scala> import cats.implicits._
* scala> val F = Foldable[List]
* scala> F.sequenceU_(List(Either.right[String, Int](333), Right(444)))
* res0: Either[String, Unit] = Right(())
* scala> F.sequenceU_(List(Either.right[String, Int](333), Left("boo")))
* res1: Either[String, Unit] = Left(boo)
* scala> F.sequenceU_(List(Xor.right[String, Int](333), Xor.Right(444)))
* res0: Xor[String, Unit] = Right(())
* scala> F.sequenceU_(List(Xor.right[String, Int](333), Xor.Left("boo")))
* res1: Xor[String, Unit] = Left(boo)
* }}}
*
* Note that using `sequence_` instead of `sequenceU_` would not compile without
Expand Down
8 changes: 5 additions & 3 deletions core/src/main/scala/cats/Monad.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package cats

import simulacrum.typeclass

import cats.data.Xor

/**
* Monad.
*
Expand All @@ -21,9 +23,9 @@ import simulacrum.typeclass
* to write this method (all cats types have a stack safe version
* of this). When this method is safe you can find an `implicit r: RecursiveTailRecM`.
*/
protected def defaultTailRecM[A, B](a: A)(fn: A => F[Either[A, B]]): F[B] =
protected def defaultTailRecM[A, B](a: A)(fn: A => F[Xor[A, B]]): F[B] =
flatMap(fn(a)) {
case Right(b) => pure(b)
case Left(nextA) => defaultTailRecM(nextA)(fn)
case Xor.Right(b) => pure(b)
case Xor.Left(nextA) => defaultTailRecM(nextA)(fn)
}
}
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/MonadCombine.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import simulacrum.typeclass
* Fold over the inner structure to combine all of the values with
* our combine method inherited from MonoidK. The result is for us
* to accumulate all of the "interesting" values of the inner G, so
* if G is Option, we collect all the Some values, if G is Either,
* if G is Option, we collect all the Some values, if G is Xor,
* we collect all the Right values, etc.
*/
def unite[G[_], A](fga: F[G[A]])(implicit G: Foldable[G]): F[A] =
Expand Down
15 changes: 9 additions & 6 deletions core/src/main/scala/cats/Traverse.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ import simulacrum.typeclass
*
* Example:
* {{{
* scala> import cats.data.Xor
* scala> import cats.implicits._
* scala> def parseInt(s: String): Option[Int] = Either.catchOnly[NumberFormatException](s.toInt).toOption
* scala> def parseInt(s: String): Option[Int] = Xor.catchOnly[NumberFormatException](s.toInt).toOption
* scala> List("1", "2", "3").traverse(parseInt)
* res0: Option[List[Int]] = Some(List(1, 2, 3))
* scala> List("1", "two", "3").traverse(parseInt)
Expand All @@ -38,13 +39,14 @@ import simulacrum.typeclass
*
* Example:
* {{{
* scala> import cats.data.Xor
* scala> import cats.implicits._
* scala> def parseInt(s: String): Either[String, Int] = Either.catchOnly[NumberFormatException](s.toInt).leftMap(_ => "no number")
* scala> def parseInt(s: String): Xor[String, Int] = Xor.catchOnly[NumberFormatException](s.toInt).leftMap(_ => "no number")
* scala> val ns = List("1", "2", "3")
* scala> ns.traverseU(parseInt)
* res0: Either[String, List[Int]] = Right(List(1, 2, 3))
* scala> ns.traverse[Either[String, ?], Int](parseInt)
* res1: Either[String, List[Int]] = Right(List(1, 2, 3))
* res0: Xor[String, List[Int]] = Right(List(1, 2, 3))
* scala> ns.traverse[Xor[String, ?], Int](parseInt)
* res1: Xor[String, List[Int]] = Right(List(1, 2, 3))
* }}}
*/
def traverseU[A, GB](fa: F[A])(f: A => GB)(implicit U: Unapply[Applicative, GB]): U.M[F[U.A]] =
Expand All @@ -55,8 +57,9 @@ import simulacrum.typeclass
*
* Example:
* {{{
* scala> import cats.data.Xor
* scala> import cats.implicits._
* scala> def parseInt(s: String): Option[Int] = Either.catchOnly[NumberFormatException](s.toInt).toOption
* scala> def parseInt(s: String): Option[Int] = Xor.catchOnly[NumberFormatException](s.toInt).toOption
* scala> val x = Option(List("1", "two", "3"))
* scala> x.traverseM(_.map(parseInt))
* res0: List[Option[Int]] = List(Some(1), None, Some(3))
Expand Down
20 changes: 12 additions & 8 deletions core/src/main/scala/cats/arrow/Choice.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package cats
package arrow

import cats.data.Xor

import simulacrum.typeclass

@typeclass trait Choice[F[_, _]] extends Category[F] {
Expand All @@ -11,35 +13,37 @@ import simulacrum.typeclass
*
* Example:
* {{{
* scala> import cats.data.Xor
* scala> import cats.implicits._
* scala> val b: Boolean => String = _ + " is a boolean"
* scala> val i: Int => String = _ + " is an integer"
* scala> val f: (Either[Boolean, Int]) => String = Choice[Function1].choice(b, i)
* scala> val f: (Boolean Xor Int) => String = Choice[Function1].choice(b, i)
*
* scala> f(Right(3))
* scala> f(Xor.right(3))
* res0: String = 3 is an integer
*
* scala> f(Left(false))
* scala> f(Xor.left(false))
* res0: String = false is a boolean
* }}}
*/
def choice[A, B, C](f: F[A, C], g: F[B, C]): F[Either[A, B], C]
def choice[A, B, C](f: F[A, C], g: F[B, C]): F[Xor[A, B], C]

/**
* An `F` that, given a source `A` on either the right or left side, will
* return that same `A` object.
*
* Example:
* {{{
* scala> import cats.data.Xor
* scala> import cats.implicits._
* scala> val f: (Either[Int, Int]) => Int = Choice[Function1].codiagonal[Int]
* scala> val f: (Int Xor Int) => Int = Choice[Function1].codiagonal[Int]
*
* scala> f(Right(3))
* scala> f(Xor.right(3))
* res0: Int = 3
*
* scala> f(Left(3))
* scala> f(Xor.left(3))
* res1: Int = 3
* }}}
*/
def codiagonal[A]: F[Either[A, A], A] = choice(id, id)
def codiagonal[A]: F[Xor[A, A], A] = choice(id, id)
}
6 changes: 3 additions & 3 deletions core/src/main/scala/cats/arrow/FunctionK.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package cats
package arrow

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

trait FunctionK[F[_], G[_]] extends Serializable { self =>
def apply[A](fa: F[A]): G[A]
Expand All @@ -17,8 +17,8 @@ trait FunctionK[F[_], G[_]] extends Serializable { self =>
def or[H[_]](h: FunctionK[H, G]): FunctionK[Coproduct[F, H, ?], G] =
new FunctionK[Coproduct[F, H, ?], G] {
def apply[A](fa: Coproduct[F, H, A]): G[A] = fa.run match {
case Left(ff) => self(ff)
case Right(gg) => h(gg)
case Xor.Left(ff) => self(ff)
case Xor.Right(gg) => h(gg)
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions core/src/main/scala/cats/data/Cokleisli.scala
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ private[data] sealed abstract class CokleisliInstances extends CokleisliInstance
override def map[B, C](fa: Cokleisli[F, A, B])(f: B => C): Cokleisli[F, A, C] =
fa.map(f)

def tailRecM[B, C](b: B)(fn: B => Cokleisli[F, A, Either[B, C]]): Cokleisli[F, A, C] =
def tailRecM[B, C](b: B)(fn: B => Cokleisli[F, A, Xor[B, C]]): Cokleisli[F, A, C] =
Cokleisli({ (fa: F[A]) =>
@tailrec
def loop(c: Cokleisli[F, A, Either[B, C]]): C = c.run(fa) match {
case Right(c) => c
case Left(bb) => loop(fn(bb))
def loop(c: Cokleisli[F, A, Xor[B, C]]): C = c.run(fa) match {
case Xor.Right(c) => c
case Xor.Left(bb) => loop(fn(bb))
}
loop(fn(b))
})
Expand Down
17 changes: 8 additions & 9 deletions core/src/main/scala/cats/data/Coproduct.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ package data

import cats.arrow.FunctionK
import cats.functor.Contravariant
import cats.syntax.either._

/** `F` on the left and `G` on the right of [[scala.util.Either]].
/** `F` on the left and `G` on the right of [[Xor]].
*
* @param run The underlying [[scala.util.Either]].
* @param run The underlying [[Xor]].
*/
final case class Coproduct[F[_], G[_], A](run: Either[F[A], G[A]]) {
final case class Coproduct[F[_], G[_], A](run: F[A] Xor G[A]) {

import Coproduct._

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

def leftc[F[_], G[_], A](x: F[A]): Coproduct[F, G, A] =
Coproduct(Left(x))
Coproduct(Xor.left(x))

def rightc[F[_], G[_], A](x: G[A]): Coproduct[F, G, A] =
Coproduct(Right(x))
Coproduct(Xor.right(x))

final class CoproductLeft[G[_]] private[Coproduct] {
def apply[F[_], A](fa: F[A]): Coproduct[F, G, A] = Coproduct(Left(fa))
def apply[F[_], A](fa: F[A]): Coproduct[F, G, A] = Coproduct(Xor.left(fa))
}

final class CoproductRight[F[_]] private[Coproduct] {
def apply[G[_], A](ga: G[A]): Coproduct[F, G, A] = Coproduct(Right(ga))
def apply[G[_], A](ga: G[A]): Coproduct[F, G, A] = Coproduct(Xor.right(ga))
}

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

private[data] sealed abstract class CoproductInstances3 {

implicit def catsDataEqForCoproduct[F[_], G[_], A](implicit E: Eq[Either[F[A], G[A]]]): Eq[Coproduct[F, G, A]] =
implicit def catsDataEqForCoproduct[F[_], G[_], A](implicit E: Eq[F[A] Xor G[A]]): Eq[Coproduct[F, G, A]] =
Eq.by(_.run)

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