package either
trait Either[+E, +A] {
def map[B](f: A => B): Either[E, B] = this match {
case Left(e) => Left(e)
case Right(a) => Right(f(a))
}
def flatMap[EE >: E, B](f: A => Either[EE, B]): Either[EE, B] = this match {
case Left(e) => Left(e)
case Right(a) => f(a)
}
def orElse[EE >: E, B >: A](b: => Either[EE, B]): Either[EE, B] = this match {
case Left(_) => b
case Right(a) => Right(a)
}
def map2[EE >: E, B, C](b: Either[EE, B])(f: (A, B) => C): Either[EE, C] =
for {
aa <- this
bb <- b
} yield f(aa, bb)
}
case class Left[+E](value: E) extends Either[E, Nothing]
case class Right[+A](value: A) extends Either[Nothing, A]
object run {
def main(args: Array[String]): Unit = {
val r = Right(3)
val l: Either[String, Int] = Left("error")
println(r map (_ + 1))
println(l map (_ + 1))
println(r flatMap ((a: Int) => Right(a + 1)))
println(l flatMap ((a: Int) => Right(a + 1)))
println(r orElse Right(0))
println(l orElse Right(0))
def add(a: Int, b: Int): Int = a + b
println(r.map2(r)(_ + _))
println(r.map2(l)(_ + _))
println(l.map2(r)(_ + _))
println(l.map2(l)(_ + _))
}
}
Right(4)
Left(error)
Right(4)
Left(error)
Right(3)
Right(0)
Right(6)
Left(error)
Left(error)
Left(error)