All Downloads are FREE. Search and download functionalities are using the official Maven repository.

teststate.data.Or.scala Maven / Gradle / Ivy

The newest version!
package teststate.data


sealed abstract class Or[+A, +B] extends Product with Serializable {
  def fold[C](l: A => C, r: B => C): C
  def cata[C](l: Left[A] => C, r: Right[B] => C): C

  final def isLeft: Boolean =
    !isRight

  final def isRight: Boolean =
    this match {
      case _: Right[B] => true
      case _ => false
    }

  final def exists(f: B => Boolean): Boolean =
    fold(_ => false, f)

  final def flatMap[C >: A, D](f: B => C Or D): C Or D =
    this match {
      case Right(b) => f(b)
      case l: Left[A] => l
    }

  final def map[C >: A, D](f: B => D): C Or D =
    flatMap(b => Right(f(b)))

  final def flatten[C, D](implicit ev: Or[A, B] <:< Or[C, C Or D]): C Or D =
    ev(this).flatMap(identity)

  final def >>[C >: A, D](r: => C Or D): C Or D =
    flatMap(_ => r)

  final def set[C >: A, D](d: => D): C Or D =
    this >> Right(d)

  final def bimap[C, D](l: A => C, r: B => D): C Or D =
    fold(a => Left(l(a)), b => Right(r(b)))

  final def recover[C >: B](f: A => C): C =
    this match {
      case Right(b) => b
      case Left(a) => f(a)
    }

  final def leftMap[C, D >: B](f: A => C): C Or D =
    this match {
      case r: Right[B] => r
      case Left(a) => Left(f(a))
    }

  final def test[C >: A](f: B => Option[C]): C Or B =
    this match {
      case r: Right[B] =>
        f(r.right) match {
          case None => r
          case Some(a) => Left(a)
        }
      case l: Left[A] => l
    }

  final def leftOption: Option[A] =
    fold(Some(_), _ => None)

  final def toOption: Option[B] =
    fold(_ => None, Some(_))

  final def toOptionMap[C](f: B => C): Option[C] =
    fold(_ => None, b => Some(f(b)))

  final def toTri: Tri[A, B] =
    toTriFlatMap(Passed(_))

  final def toTriMap[C](f: B => C): Tri[A, C] =
    toTriFlatMap(b => Passed(f(b)))

  final def toTriFlatMap[C >: A, D](f: B => Tri[C, D]): Tri[C, D] =
    fold(Failed(_), f)

  final def toEither: Either[A, B] =
    fold(scala.Left(_), scala.Right(_))
}

final case class Left[+A](left: A) extends Or[A, Nothing] {
  override def fold[C](l: A => C, r: Nothing => C): C = l(left)
  override def cata[C](l: Left[A] => C, r: Right[Nothing] => C): C = l(this)
}

final case class Right[+B](right: B) extends Or[Nothing, B] {
  override def fold[C](l: Nothing => C, r: B => C): C = r(right)
  override def cata[C](l: Left[Nothing] => C, r: Right[B] => C): C = r(this)
}

object Or {
  def liftLeft[A, B](o: Option[A]): A Or Unit =
    liftLeft(o, ())

  def liftLeft[A, B](o: Option[A], b: => B): A Or B =
    o.fold[A Or B](Right(b))(Left(_))

  def fromScalaEither[A, B](e: A Either B): A Or B =
    e.fold(Left(_), Right(_))

  val rightTrue = Right(true)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy