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

Partial revert of #1289 #1306

Merged
merged 1 commit into from
Aug 20, 2016
Merged
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
14 changes: 7 additions & 7 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.
*
* 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
4 changes: 2 additions & 2 deletions core/src/main/scala/cats/Foldable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ 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 `scala.util.Either`
*
* {{{
* scala> import cats.implicits._
Expand Down Expand Up @@ -251,7 +251,7 @@ 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 `scala.util.Either`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason validate was giving me "Could not find any members to link for "scala.util.Either" so I went for the easy way out.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I totally endorse this. I may-or-may-not have made a snarky tweet about Scaladoc today related to this.

*
* {{{
* scala> import cats.implicits._
Expand Down
19 changes: 11 additions & 8 deletions core/src/main/scala/cats/arrow/Choice.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cats
package arrow

import cats.data.Xor
import simulacrum.typeclass

@typeclass trait Choice[F[_, _]] extends Category[F] {
Expand All @@ -11,35 +12,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: Xor[Boolean, 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: (Xor[Int, 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.{Coproduct, Xor}

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
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 [[cats.data.Xor]].
*
* @param run The underlying [[scala.util.Either]].
* @param run The underlying [[cats.data.Xor]].
*/
final case class Coproduct[F[_], G[_], A](run: Either[F[A], G[A]]) {
final case class Coproduct[F[_], G[_], A](run: Xor[F[A], 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[Xor[F[A], 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
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/data/EitherT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ private[data] trait EitherTMonadError[F[_], L] extends MonadError[EitherT[F, L,
case r @ Right(_) => F.pure(r)
})
def raiseError[A](e: L): EitherT[F, L, A] = EitherT.left(F.pure(e))
override def attempt[A](fla: EitherT[F, L, A]): EitherT[F, L, Either[L, A]] = EitherT.right(fla.value)
override def attempt[A](fla: EitherT[F, L, A]): EitherT[F, L, Xor[L, A]] = EitherT.right(F.map(fla.value)(_.toXor))
override def recover[A](fla: EitherT[F, L, A])(pf: PartialFunction[L, A]): EitherT[F, L, A] =
fla.recover(pf)
override def recoverWith[A](fla: EitherT[F, L, A])(pf: PartialFunction[L, EitherT[F, L, A]]): EitherT[F, L, A] =
Expand Down
12 changes: 6 additions & 6 deletions core/src/main/scala/cats/data/Ior.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ import scala.annotation.tailrec
* - `[[Ior.Right Right]][B]`
* - `[[Ior.Both Both]][A, B]`
*
* `A [[Ior]] B` is similar to `Either[A, B]`, except that it can represent the simultaneous presence of
* `A [[Ior]] B` is similar to `Xor[A, B]`, except that it can represent the simultaneous presence of
* an `A` and a `B`. It is right-biased so methods such as `map` and `flatMap` operate on the
* `B` value. Some methods, like `flatMap`, handle the presence of two [[Ior.Both Both]] values using a
* `[[Semigroup]][A]`, while other methods, like [[toEither]], ignore the `A` value in a [[Ior.Both Both]].
* `[[Semigroup]][A]`, while other methods, like [[toXor]], ignore the `A` value in a [[Ior.Both Both]].
*
* `A [[Ior]] B` is isomorphic to `Either[Either[A, B], (A, B)]`, but provides methods biased toward `B`
* `A [[Ior]] B` is isomorphic to `Xor[Xor[A, B], (A, B)]`, but provides methods biased toward `B`
* values, regardless of whether the `B` values appear in a [[Ior.Right Right]] or a [[Ior.Both Both]].
* The isomorphic [[scala.util.Either]] form can be accessed via the [[unwrap]] method.
* The isomorphic [[cats.data.Xor]] form can be accessed via the [[unwrap]] method.
*/
sealed abstract class Ior[+A, +B] extends Product with Serializable {

Expand All @@ -36,10 +36,10 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable {
final def right: Option[B] = fold(_ => None, b => Some(b), (_, b) => Some(b))
final def onlyLeft: Option[A] = fold(a => Some(a), _ => None, (_, _) => None)
final def onlyRight: Option[B] = fold(_ => None, b => Some(b), (_, _) => None)
final def onlyLeftOrRight: Option[Either[A, B]] = fold(a => Some(Left(a)), b => Some(Right(b)), (_, _) => None)
final def onlyLeftOrRight: Option[Xor[A, B]] = fold(a => Some(Xor.Left(a)), b => Some(Xor.Right(b)), (_, _) => None)
final def onlyBoth: Option[(A, B)] = fold(_ => None, _ => None, (a, b) => Some((a, b)))
final def pad: (Option[A], Option[B]) = fold(a => (Some(a), None), b => (None, Some(b)), (a, b) => (Some(a), Some(b)))
final def unwrap: Either[Either[A, B], (A, B)] = fold(a => Left(Left(a)), b => Left(Right(b)), (a, b) => Right((a, b)))
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)))

final def toXor: A Xor B = fold(Xor.left, Xor.right, (_, b) => Xor.right(b))
final def toEither: Either[A, B] = fold(Left(_), Right(_), (_, b) => Right(b))
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/data/Kleisli.scala
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ private[data] sealed abstract class KleisliInstances extends KleisliInstances0 {
new Choice[Kleisli[F, ?, ?]] {
def id[A]: Kleisli[F, A, A] = Kleisli(ev.pure(_))

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

def compose[A, B, C](f: Kleisli[F, B, C], g: Kleisli[F, A, B]): Kleisli[F, A, C] =
Expand Down
8 changes: 4 additions & 4 deletions core/src/main/scala/cats/data/OptionT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,11 @@ final case class OptionT[F[_], A](value: F[Option[A]]) {
case None => default
})

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

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

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

Expand Down
13 changes: 9 additions & 4 deletions core/src/main/scala/cats/data/Validated.scala
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,11 @@ sealed abstract class Validated[+E, +A] extends Product with Serializable {
def toXor: Xor[E, A] = fold(Xor.Left.apply, Xor.Right.apply)

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

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

/**
* Converts an `Xor[A, B]` to an `Validated[A, B]`.
*/
def fromXor[A, B](e: Xor[A, B]): Validated[A, B] = e.fold(invalid, valid)

/**
* Converts an `Option[B]` to an `Validated[A, B]`, where the provided `ifNone` values is returned on
* the invalid of the `Validated` when the specified `Option` is `None`.
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/data/Xor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ private[data] sealed abstract class XorInstances extends XorInstances1 {
override def map[B, C](fa: A Xor B)(f: B => C): A Xor C = fa.map(f)
override def map2Eval[B, C, Z](fb: A Xor B, fc: Eval[A Xor C])(f: (B, C) => Z): Eval[A Xor Z] =
fb.map2Eval(fc)(f)
override def attempt[B](fab: A Xor B): A Xor (Either[A, B]) = Xor.right(fab.toEither)
override def attempt[B](fab: A Xor B): A Xor (Xor[A, B]) = Xor.right(fab)
override def recover[B](fab: A Xor B)(pf: PartialFunction[A, B]): A Xor B =
fab recover pf
override def recoverWith[B](fab: A Xor B)(pf: PartialFunction[A, A Xor B]): A Xor B =
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/data/XorT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ private[data] trait XorTMonadError[F[_], L] extends MonadError[XorT[F, L, ?], L]
case r @ Xor.Right(_) => F.pure(r)
})
def raiseError[A](e: L): XorT[F, L, A] = XorT.left(F.pure(e))
override def attempt[A](fla: XorT[F, L, A]): XorT[F, L, Either[L, A]] = XorT.right(fla.toEither)
override def attempt[A](fla: XorT[F, L, A]): XorT[F, L, Xor[L, A]] = XorT.right(fla.value)
override def recover[A](fla: XorT[F, L, A])(pf: PartialFunction[L, A]): XorT[F, L, A] =
fla.recover(pf)
override def recoverWith[A](fla: XorT[F, L, A])(pf: PartialFunction[L, XorT[F, L, A]]): XorT[F, L, A] =
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/scala/cats/instances/either.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cats
package instances

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

override def attempt[B](fab: Either[A, B]): Either[A, Either[A, B]] = Right(fab)
override def attempt[B](fab: Either[A, B]): Either[A, Xor[A, B]] = Right(fab.toXor)
override def recover[B](fab: Either[A, B])(pf: PartialFunction[A, B]): Either[A, B] =
fab recover pf
override def recoverWith[B](fab: Either[A, B])(pf: PartialFunction[A, Either[A, B]]): Either[A, B] =
Expand Down
7 changes: 4 additions & 3 deletions core/src/main/scala/cats/instances/function.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cats
package instances

import cats.arrow.{Arrow, Choice}
import cats.data.Xor
import cats.functor.Contravariant
import annotation.tailrec

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

implicit val catsStdInstancesForFunction1: Choice[Function1] with Arrow[Function1] =
new Choice[Function1] with Arrow[Function1] {
def choice[A, B, C](f: A => C, g: B => C): Either[A, B] => C =
def choice[A, B, C](f: A => C, g: B => C): Xor[A, B] => C =
_ match {
case Left(a) => f(a)
case Right(b) => g(b)
case Xor.Left(a) => f(a)
case Xor.Right(b) => g(b)
}

def lift[A, B](f: A => B): A => B = f
Expand Down
5 changes: 3 additions & 2 deletions core/src/main/scala/cats/instances/future.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cats
package instances

import cats.data.Xor
import scala.util.control.NonFatal
import scala.concurrent.{ExecutionContext, Future}

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

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

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

Expand Down
5 changes: 3 additions & 2 deletions core/src/main/scala/cats/instances/try.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package instances

import TryInstances.castFailure

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

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

override def recover[A](ta: Try[A])(pf: PartialFunction[Throwable, A]): Try[A] =
ta.recover(pf)
Expand Down
6 changes: 3 additions & 3 deletions core/src/main/scala/cats/syntax/applicativeError.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package cats
package syntax

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

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

def attempt: F[Either[E, A]] =
def attempt: F[Xor[E, A]] =
F.attempt(fa)

def attemptT: EitherT[F, E, A] =
def attemptT: XorT[F, E, A] =
F.attemptT(fa)

def recover(pf: PartialFunction[E, A]): F[A] =
Expand Down
Loading