scalaz.These.scala Maven / Gradle / Ivy
The newest version!
package scalaz
/** @since 7.0.3 */
sealed abstract class \&/[A, B] extends Product with Serializable {
import \&/._
def isThis: Boolean =
this match {
case This(_) => true
case That(_) => false
case Both(_, _) => false
}
def isThat: Boolean =
this match {
case This(_) => false
case That(_) => true
case Both(_, _) => false
}
def isBoth: Boolean =
this match {
case This(_) => false
case That(_) => false
case Both(_, _) => true
}
def a: Option[A] =
this match {
case This(a) => Some(a)
case That(_) => None
case Both(a, _) => Some(a)
}
def b: Option[B] =
this match {
case This(_) => None
case That(b) => Some(b)
case Both(_, b) => Some(b)
}
def onlyThis: Option[A] =
this match {
case This(a) => Some(a)
case That(_) => None
case Both(_, _) => None
}
def onlyThat: Option[B] =
this match {
case This(_) => None
case That(b) => Some(b)
case Both(_, _) => None
}
def onlyThisOrThat: Option[A \/ B] =
this match {
case This(a) => Some(-\/(a))
case That(b) => Some(\/-(b))
case Both(_, _) => None
}
def onlyBoth: Option[(A, B)] =
this match {
case This(_) => None
case That(_) => None
case Both(a, b) => Some((a, b))
}
def pad: (Option[A], Option[B]) =
this match {
case This(a) => (Some(a), None)
case That(b) => (None, Some(b))
case Both(a, b) => (Some(a), Some(b))
}
def fold[X](s: A => X, t: B => X, q: (A, B) => X): X =
this match {
case This(a) => s(a)
case That(b) => t(b)
case Both(a, b) => q(a, b)
}
def swap: (B \&/ A) =
this match {
case This(a) => That(a)
case That(b) => This(b)
case Both(a, b) => Both(b, a)
}
def unary_~ : (B \&/ A) =
swap
def swapped[AA, BB](k: (B \&/ A) => (BB \&/ AA)): (AA \&/ BB) =
k(swap).swap
def ~[AA, BB](k: (B \&/ A) => (BB \&/ AA)): (AA \&/ BB) =
swapped(k)
def append[AA >: A, BB >: B](that: => (AA \&/ BB))(implicit SA: Semigroup[AA], SB: Semigroup[BB]): (AA \&/ BB) =
(this, that) match {
case (This(a1), This(a2)) => This(SA.append(a1, a2))
case (This(a1), Both(a2, b)) => Both(SA.append(a1, a2), b)
case (This(a), That(b)) => Both(a, b)
case (Both(a1, b), This(a2)) => Both(SA.append(a1, a2), b)
case (Both(a1, b1), Both(a2, b2)) =>
Both(SA.append(a1, a2), SB.append(b1, b2))
case (Both(a, b1), That(b2)) => Both(a, SB.append(b1, b2))
case (That(b), This(a)) => Both(a, b)
case (That(b1), Both(a, b2)) => Both(a, SB.append(b1, b2))
case (That(b1), That(b2)) => That( SB.append(b1, b2))
}
def bimap[C, D](f: A => C, g: B => D): (C \&/ D) =
this match {
case This(a) => This(f(a))
case That(b) => That(g(b))
case Both(a, b) => Both(f(a), g(b))
}
def leftMap[C](f: A => C): (C \&/ B) =
bimap(f, identity)
def bitraverse[F[_]: Apply, C, D](f: A => F[C], g: B => F[D]): F[C \&/ D] =
this match {
case This(a) =>
Functor[F].map(f(a))(This(_))
case That(b) =>
Functor[F].map(g(b))(That(_))
case Both(a, b) =>
Apply[F].apply2(f(a), g(b)) {
case (c, d) => Both(c, d): C \&/ D
}
}
def map[D](g: B => D): (A \&/ D) =
bimap(identity, g)
def traverse[F[_]: Applicative, D](g: B => F[D]): F[A \&/ D] =
this match {
case a @ This(_) =>
Applicative[F].point(a.coerceThat)
case That(b) =>
Functor[F].map(g(b))(That(_))
case Both(a, b) =>
Functor[F].map(g(b))(Both(a, _): A \&/ D)
}
def foreach(g: B => Unit): Unit =
fold(_ => (), g, (_, b) => g(b))
def flatMap[D](g: B => (A \&/ D))(implicit M: Semigroup[A]): (A \&/ D) =
this match {
case a @ This(_) =>
a.coerceThat
case That(b) =>
g(b)
case Both(a, b) =>
g(b) match {
case This(aa) =>
This(M.append(a, aa))
case That(bb) =>
Both(a, bb)
case Both(aa, bb) =>
Both(M.append(a, aa), bb)
}
}
def &&&[C](t: A \&/ C)(implicit M: Semigroup[A]): A \&/ (B, C) =
for {
b <- this
c <- t
} yield (b, c)
def foldRight[Z](z: => Z)(f: (B, => Z) => Z): Z =
b match {
case None => z
case Some(bb) => f(bb, z)
}
def foldMap[C](f: B => C)(implicit M: Monoid[C]): C =
b match {
case None => M.zero
case Some(bb) => f(bb)
}
def bifoldRight[Z](z: => Z)(f: (A, => Z) => Z)(g: (B, => Z) => Z): Z =
this match{
case This(a) => f(a, z)
case That(b) => g(b, z)
case Both(a, b) => f(a, g(b, z))
}
def bifoldMap[M](f: A => M)(g: B => M)(implicit M: Semigroup[M]): M =
fold(f, g, (a, b) => M.append(f(a), g(b)))
def exists(p: B => Boolean): Boolean =
b exists p
def forall(p: B => Boolean): Boolean =
b forall p
def toList: List[B] =
b.toList
def toIList[BB >: B]: IList[BB] = fold(_ => INil(), IList(_), (_, b) => IList(b))
def getOrElse[BB >: B](bb: => BB): BB =
b getOrElse bb
def |[BB >: B](bb: => BB): BB =
getOrElse(bb)
def valueOr[BB >: B](x: A => BB)(implicit M: Semigroup[BB]): BB =
this match {
case This(a) =>
x(a)
case That(b) =>
b
case Both(a, b) =>
M.append(x(a), b)
}
def ===[AA >: A, BB >: B](x: AA \&/ BB)(implicit EA: Equal[AA], EB: Equal[BB]): Boolean =
this match {
case This(a) =>
x match {
case This(aa) =>
EA.equal(a, aa)
case _ =>
false
}
case That(b) =>
x match {
case That(bb) =>
EB.equal(b, bb)
case _ =>
false
}
case Both(a, b) =>
x match {
case Both(aa, bb) =>
EA.equal(a, aa) && EB.equal(b, bb)
case _ =>
false
}
}
}
object \&/ extends TheseInstances {
final case class This[A, B](aa: A) extends (A \&/ B) {
def coerceThat[C]: A \&/ C = this.asInstanceOf[A \&/ C]
}
final case class That[A, B](bb: B) extends (A \&/ B) {
def coerceThis[C]: C \&/ B = this.asInstanceOf[C \&/ B]
}
final case class Both[A, B](aa: A, bb: B) extends (A \&/ B)
def apply[A, B](a: A, b: B): These[A, B] =
Both(a, b)
def unapply[A, B](t: Both[A, B]): Some[(A, B)] =
Some((t.aa, t.bb))
import scalaz.std.list._
def concatThisList[A, B](x: List[A \&/ B]): List[A] =
concatThis[List, A, B](x)
def concatThisIList[A, B](x: IList[A \&/ B]): IList[A] =
concatThis[IList, A, B](x)
def concatThisStream[A, B](x: EphemeralStream[A \&/ B]): EphemeralStream[A] =
concatThis[EphemeralStream, A, B](x)
def concatThis[F[_], A, B](x: F[A \&/ B])(implicit M: MonadPlus[F]): F[A] =
M.bind(x) {
case This(a) =>
M.point(a)
case That(_) =>
M.empty
case Both(a, _) =>
M.point(a)
}
def concatThatList[A, B](x: List[A \&/ B]): List[B] =
concatThat[List, A, B](x)
def concatThatIList[A, B](x: IList[A \&/ B]): IList[B] =
concatThat[IList, A, B](x)
def concatThatStream[A, B](x: EphemeralStream[A \&/ B]): EphemeralStream[B] =
concatThat[EphemeralStream, A, B](x)
def concatThat[F[_], A, B](x: F[A \&/ B])(implicit M: MonadPlus[F]): F[B] =
M.bind(x) {
case This(_) =>
M.empty
case That(b) =>
M.point(b)
case Both(_, b) =>
M.point(b)
}
def unalignList[A, B](x: List[A \&/ B]): (List[A], List[B]) =
unalign[List, A, B](x)
def unalignIList[A, B](x: IList[A \&/ B]): (IList[A], IList[B]) =
unalign[IList, A, B](x)
def unalignStream[A, B](x: EphemeralStream[A \&/ B]): (EphemeralStream[A], EphemeralStream[B]) =
unalign[EphemeralStream, A, B](x)
def unalign[F[_], A, B](x: F[A \&/ B])(implicit M: MonadPlus[F]): (F[A], F[B]) =
(concatThis(x), concatThat(x))
def merge[A](t: A \&/ A)(implicit S: Semigroup[A]): A =
t match {
case This(a) =>
a
case That(a) =>
a
case Both(a1, a2) =>
S.append(a1, a2)
}
def tailrecM[L, A, B](a: A)(f: A => L \&/ (A \/ B))(implicit L: Semigroup[L]): L \&/ B = {
@annotation.tailrec
def go(x: L \&/ (A \/ B)): L \&/ B = x match {
case t @ This(_) => t.coerceThat
case That(-\/(a)) => go(f(a))
case That(\/-(b)) => \&/.That(b)
case Both(l, -\/(a)) => f(a) match {
case This(l1) => \&/.This(L.append(l, l1))
case That(ab) => go(\&/.Both(l, ab))
case Both(l1, ab) => go(\&/.Both(L.append(l, l1), ab))
}
case Both(l, \/-(b)) => \&/.Both(l, b)
}
go(f(a))
}
}
sealed abstract class TheseInstances extends TheseInstances0 {
type These[A, B] =
A \&/ B
implicit def TheseBand[A: Band, B: Band]: Band[A \&/ B] =
new Band[A \&/ B] {
def append(f1: A \&/ B, f2: => A \&/ B) =
f1 append f2
}
}
sealed abstract class TheseInstances0 extends TheseInstances1 {
implicit def TheseIsCovariantRight[A]: IsCovariant[\&/[A, *]] =
IsCovariant.force[\&/[A, *]]
implicit def TheseIsCovariantLeft[A]: IsCovariant[\&/[*, A]] =
IsCovariant.force[\&/[*, A]]
implicit def TheseInstance0[L: Semigroup]: Monad[\&/[L, *]] & BindRec[\&/[L, *]] =
new Monad[\&/[L, *]] with BindRec[\&/[L, *]] {
def tailrecM[A, B](a: A)(f: A => L \&/ (A \/ B)): L \&/ B =
\&/.tailrecM(a)(f)
override def map[A, B](x: L \&/ A)(f: A => B) =
x map f
def bind[A, B](fa: L \&/ A)(f: A => L \&/ B) =
fa flatMap f
def point[A](a: => A): L \&/ A =
\&/.That(a)
}
implicit val TheseBitraverse: Bitraverse[\&/] =
new Bitraverse[\&/] {
override def bimap[A, B, C, D](fab: A \&/ B)(f: A => C, g: B => D) =
fab.bimap(f, g)
override def bifoldMap[A, B, M](fa: A \&/ B)(f: A => M)(g: B => M)(implicit F: Monoid[M]) =
fa.bifoldMap(f)(g)
override def bifoldRight[A, B, C](fa: A \&/ B, z: => C)(f: (A, => C) => C)(g: (B, => C) => C) =
fa.bifoldRight(z)(f)(g)
def bitraverseImpl[G[_] : Applicative, A, B, C, D](fab: A \&/ B)(f: A => G[C], g: B => G[D]) =
fab.bitraverse(f, g)
}
implicit final def TheseOrder[A, B](implicit A: Order[A], B: Order[B]): Order[A \&/ B] =
new Order[A \&/ B] {
override def equal(x: A \&/ B, y: A \&/ B) =
x === y
override def order(x: A \&/ B, y: A \&/ B) = x match {
case \&/.This(a1) =>
y match {
case \&/.This(a2) =>
A.order(a1, a2)
case _ =>
Ordering.GT
}
case \&/.That(b1) =>
y match {
case \&/.That(b2) =>
B.order(b1, b2)
case _ =>
Ordering.LT
}
case \&/.Both(a1, b1) =>
y match {
case \&/.Both(a2, b2) =>
A.order(a1, a2) match {
case Ordering.EQ => B.order(b1, b2)
case o => o
}
case \&/.This(_) =>
Ordering.LT
case \&/.That(_) =>
Ordering.GT
}
}
}
}
sealed abstract class TheseInstances1 {
implicit def TheseInstance1[L]: Traverse[\&/[L, *]] & Cobind[\&/[L, *]] =
new Traverse[\&/[L, *]] with Cobind[\&/[L, *]] {
def traverseImpl[G[_] : Applicative, A, B](fa: L \&/ A)(f: A => G[B]) =
fa traverse f
override def foldMap[A, B](fa: L \&/ A)(f: A => B)(implicit F: Monoid[B]) =
fa foldMap f
override def foldRight[A, B](fa: L \&/ A, z: => B)(f: (A, => B) => B) =
fa.foldRight(z)(f)
def cobind[A, B](fa: L \&/ A)(f: (L \&/ A) => B): L \&/ B =
\&/.That(f(fa))
}
implicit def TheseEqual[A, B](implicit EA: Equal[A], EB: Equal[B]): Equal[A \&/ B] =
Equal.equal(_ === _)
implicit def TheseSemigroup[A, B](implicit SA: Semigroup[A], SB: Semigroup[B]): Semigroup[A \&/ B] =
Semigroup.instance(_.append(_))
implicit def TheseShow[A, B](implicit SA: Show[A], SB: Show[B]): Show[A \&/ B] = {
import scalaz.syntax.show._
Show.show {
case \&/.This(a) => cord"This($a)"
case \&/.That(b) => cord"That($b)"
case \&/.Both(a, b) => cord"Both($a,$b)"
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy