Skip to content

Commit

Permalink
Partially revert 4530d3a. Add back variance on methods in EitherT and…
Browse files Browse the repository at this point in the history
… Either syntax.
  • Loading branch information
Marcin Rzeźnicki authored and marcin-rzeznicki committed Dec 29, 2016
1 parent 974b840 commit d084def
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 35 deletions.
21 changes: 11 additions & 10 deletions core/src/main/scala/cats/data/EitherT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {

def swap(implicit F: Functor[F]): EitherT[F, B, A] = EitherT(F.map(value)(_.swap))

def getOrElse(default: => B)(implicit F: Functor[F]): F[B] = F.map(value)(_.getOrElse(default))
def getOrElse[BB >: B](default: => BB)(implicit F: Functor[F]): F[BB] = F.map(value)(_.getOrElse(default))

def getOrElseF(default: => F[B])(implicit F: Monad[F]): F[B] = {
def getOrElseF[BB >: B](default: => F[BB])(implicit F: Monad[F]): F[BB] = {
F.flatMap(value) {
case Left(_) => default
case Right(b) => F.pure(b)
}
}

def orElse(default: => EitherT[F, A, B])(implicit F: Monad[F]): EitherT[F, A, B] = {
def orElse[AA, BB >: B](default: => EitherT[F, AA, BB])(implicit F: Monad[F]): EitherT[F, AA, BB] = {
EitherT(F.flatMap(value) {
case Left(_) => default.value
case r @ Right(_) => F.pure(r)
case r @ Right(_) => F.pure(r.leftCast)
})
}

Expand All @@ -46,13 +46,14 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
case other => F.pure(other)
})

def valueOr(f: A => B)(implicit F: Functor[F]): F[B] = fold(f, identity)
def valueOr[BB >: B](f: A => BB)(implicit F: Functor[F]): F[BB] = fold(f, identity)

def forall(f: B => Boolean)(implicit F: Functor[F]): F[Boolean] = F.map(value)(_.forall(f))

def exists(f: B => Boolean)(implicit F: Functor[F]): F[Boolean] = F.map(value)(_.exists(f))

def ensure(onFailure: => A)(f: B => Boolean)(implicit F: Functor[F]): EitherT[F, A, B] = EitherT(F.map(value)(_.ensure(onFailure)(f)))
def ensure[AA >: A](onFailure: => AA)(f: B => Boolean)(implicit F: Functor[F]): EitherT[F, AA, B] =
EitherT(F.map(value)(_.ensure(onFailure)(f)))

def toOption(implicit F: Functor[F]): OptionT[F, B] = OptionT(F.map(value)(_.toOption))

Expand All @@ -70,19 +71,19 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
def applyAlt[D](ff: EitherT[F, A, B => D])(implicit F: Apply[F]): EitherT[F, A, D] =
EitherT[F, A, D](F.map2(this.value, ff.value)((xb, xbd) => Apply[Either[A, ?]].ap(xbd)(xb)))

def flatMap[D](f: B => EitherT[F, A, D])(implicit F: Monad[F]): EitherT[F, A, D] =
def flatMap[AA >: A, D](f: B => EitherT[F, AA, D])(implicit F: Monad[F]): EitherT[F, AA, D] =
EitherT(F.flatMap(value) {
case l @ Left(_) => F.pure(l.rightCast)
case Right(b) => f(b).value
})

def flatMapF[D](f: B => F[Either[A, D]])(implicit F: Monad[F]): EitherT[F, A, D] =
def flatMapF[AA >: A, D](f: B => F[Either[AA, D]])(implicit F: Monad[F]): EitherT[F, AA, D] =
flatMap(f andThen EitherT.apply)

def transform[C, D](f: Either[A, B] => Either[C, D])(implicit F: Functor[F]): EitherT[F, C, D] =
EitherT(F.map(value)(f))

def subflatMap[D](f: B => Either[A, D])(implicit F: Functor[F]): EitherT[F, A, D] =
def subflatMap[AA >: A, D](f: B => Either[AA, D])(implicit F: Functor[F]): EitherT[F, AA, D] =
transform(_.flatMap(f))

def map[D](f: B => D)(implicit F: Functor[F]): EitherT[F, A, D] = bimap(identity, f)
Expand Down Expand Up @@ -110,7 +111,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
def foldRight[C](lc: Eval[C])(f: (B, Eval[C]) => Eval[C])(implicit F: Foldable[F]): Eval[C] =
F.foldRight(value, lc)((axb, lc) => axb.foldRight(lc)(f))

def merge(implicit ev: B <:< A, F: Functor[F]): F[A] = F.map(value)(_.fold(identity, ev.apply))
def merge[AA >: A](implicit ev: B <:< AA, F: Functor[F]): F[AA] = F.map(value)(_.fold(identity, ev.apply))

/**
* Similar to `Either#combine` but mapped over an `F` context.
Expand Down
50 changes: 25 additions & 25 deletions core/src/main/scala/cats/syntax/either.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,27 @@ final class EitherOps[A, B](val eab: Either[A, B]) extends AnyVal {
case Right(b) => f(b)
}

def getOrElse(default: => B): B = eab match {
def getOrElse[BB >: B](default: => BB): BB = eab match {
case Left(_) => default
case Right(b) => b
}

def orElse[C](fallback: => Either[C, B]): Either[C, B] = eab match {
def orElse[C, BB >: B](fallback: => Either[C, BB]): Either[C, BB] = eab match {
case Left(_) => fallback
case r @ Right(_) => EitherUtil.leftCast(r)
}

def recover(pf: PartialFunction[A, B]): Either[A, B] = eab match {
def recover[BB >: B](pf: PartialFunction[A, BB]): Either[A, BB] = eab match {
case Left(a) if pf.isDefinedAt(a) => Right(pf(a))
case _ => eab
}

def recoverWith(pf: PartialFunction[A, Either[A, B]]): Either[A, B] = eab match {
def recoverWith[AA >: A, BB >: B](pf: PartialFunction[A, Either[AA, BB]]): Either[AA, BB] = eab match {
case Left(a) if pf.isDefinedAt(a) => pf(a)
case _ => eab
}

def valueOr(f: A => B): B = eab match {
def valueOr[BB >: B](f: A => BB): BB = eab match {
case Left(a) => f(a)
case Right(b) => b
}
Expand All @@ -58,7 +58,7 @@ final class EitherOps[A, B](val eab: Either[A, B]) extends AnyVal {
case Right(b) => f(b)
}

def ensure(onFailure: => A)(f: B => Boolean): Either[A, B] = eab match {
def ensure[AA >: A](onFailure: => AA)(f: B => Boolean): Either[AA, B] = eab match {
case Left(_) => eab
case Right(b) => if (f(b)) eab else Left(onFailure)
}
Expand Down Expand Up @@ -90,7 +90,7 @@ final class EitherOps[A, B](val eab: Either[A, B]) extends AnyVal {

/** Returns a [[cats.data.ValidatedNel]] representation of this disjunction with the `Left` value
* as a single element on the `Invalid` side of the [[cats.data.NonEmptyList]]. */
def toValidatedNel: ValidatedNel[A, B] = eab match {
def toValidatedNel[AA >: A]: ValidatedNel[AA, B] = eab match {
case Left(a) => Validated.invalidNel(a)
case Right(b) => Validated.valid(b)
}
Expand All @@ -113,7 +113,7 @@ final class EitherOps[A, B](val eab: Either[A, B]) extends AnyVal {
case Right(b) => Right(f(b))
}

def map2Eval[C, Z](fc: Eval[Either[A, C]])(f: (B, C) => Z): Eval[Either[A, Z]] =
def map2Eval[AA >: A, C, Z](fc: Eval[Either[AA, C]])(f: (B, C) => Z): Eval[Either[AA, Z]] =
eab match {
case l @ Left(_) => Now(EitherUtil.rightCast(l))
case Right(b) => fc.map(either => new EitherOps(either).map(f(b, _)))
Expand All @@ -124,51 +124,51 @@ final class EitherOps[A, B](val eab: Either[A, B]) extends AnyVal {
case r @ Right(_) => EitherUtil.leftCast(r)
}

def flatMap[D](f: B => Either[A, D]): Either[A, D] = eab match {
def flatMap[AA >: A, D](f: B => Either[AA, D]): Either[AA, D] = eab match {
case l @ Left(_) => EitherUtil.rightCast(l)
case Right(b) => f(b)
}

def compare(that: Either[A, B])(implicit A: Order[A], B: Order[B]): Int = eab match {
def compare[AA >: A, BB >: B](that: Either[AA, BB])(implicit AA: Order[AA], BB: Order[BB]): Int = eab match {
case Left(a1) =>
that match {
case Left(a2) => A.compare(a1, a2)
case Left(a2) => AA.compare(a1, a2)
case Right(_) => -1
}
case Right(b1) =>
that match {
case Left(_) => 1
case Right(b2) => B.compare(b1, b2)
case Right(b2) => BB.compare(b1, b2)
}
}

def partialCompare(that: Either[A, B])(implicit A: PartialOrder[A], B: PartialOrder[B]): Double = eab match {
def partialCompare[AA >: A, BB >: B](that: Either[AA, BB])(implicit AA: PartialOrder[AA], BB: PartialOrder[BB]): Double = eab match {
case Left(a1) =>
that match {
case Left(a2) => A.partialCompare(a1, a2)
case Left(a2) => AA.partialCompare(a1, a2)
case Right(_) => -1
}
case Right(b1) =>
that match {
case Left(_) => 1
case Right(b2) => B.partialCompare(b1, b2)
case Right(b2) => BB.partialCompare(b1, b2)
}
}

def ===(that: Either[A, B])(implicit A: Eq[A], B: Eq[B]): Boolean = eab match {
def ===[AA >: A, BB >: B](that: Either[AA, BB])(implicit AA: Eq[AA], BB: Eq[BB]): Boolean = eab match {
case Left(a1) =>
that match {
case Left(a2) => A.eqv(a1, a2)
case Left(a2) => AA.eqv(a1, a2)
case Right(_) => false
}
case Right(b1) =>
that match {
case Left(_) => false
case Right(b2) => B.eqv(b1, b2)
case Right(b2) => BB.eqv(b1, b2)
}
}

def traverse[F[_], D](f: B => F[D])(implicit F: Applicative[F]): F[Either[A, D]] = eab match {
def traverse[F[_], AA >: A, D](f: B => F[D])(implicit F: Applicative[F]): F[Either[AA, D]] = eab match {
case l @ Left(_) => F.pure(EitherUtil.rightCast(l))
case Right(b) => F.map(f(b))(Right(_))
}
Expand Down Expand Up @@ -215,20 +215,20 @@ final class EitherOps[A, B](val eab: Either[A, B]) extends AnyVal {
* res3: Either[String, Int] = Right(7)
* }}}
*/
final def combine(that: Either[A, B])(implicit B: Semigroup[B]): Either[A, B] = eab match {
final def combine[AA >: A, BB >: B](that: Either[AA, BB])(implicit BB: Semigroup[BB]): Either[AA, BB] = eab match {
case left @ Left(_) => left
case Right(b1) => that match {
case left @ Left(_) => left
case Right(b2) => Right(B.combine(b1, b2))
case Right(b2) => Right(BB.combine(b1, b2))
}
}

def show(implicit A: Show[A], B: Show[B]): String = eab match {
case Left(a) => s"Left(${A.show(a)})"
case Right(b) => s"Right(${B.show(b)})"
def show[AA >: A, BB >: B](implicit AA: Show[AA], BB: Show[BB]): String = eab match {
case Left(a) => s"Left(${AA.show(a)})"
case Right(b) => s"Right(${BB.show(b)})"
}

def ap[C](that: Either[A, B => C]): Either[A, C] = (new EitherOps(that)).flatMap(this.map)
def ap[AA >: A, BB >: B, C](that: Either[AA, BB => C]): Either[AA, C] = new EitherOps(that).flatMap(this.map)

/**
* Transform the `Either` into a [[cats.data.EitherT]] while lifting it into the specified Applicative.
Expand Down

0 comments on commit d084def

Please sign in to comment.