sealed trait Either[A, B]
case class Left[A, B](a: A) extends Either[A, B]
case class Right[A, B](b: B) extends Either[A, B]
object Either {
implicit def eitherTMonad[A, M[_]: Monad]: Monad[({ type λ[ɑ] = M[Either[A,ɑ]] })#λ] =
new Monad[({ type λ[ɑ] = M[Either[A,ɑ]] })#λ] {
private lazy val m: Monad[M] = implicitly[Monad[M]]
def pure[B](b: B): M[Either[A, B]] =
m.pure(Right(b))
def flatMap[B, C](ma: M[Either[A, B]])(f: B => M[Either[A, C]]): M[Either[A, C]] =
m.flatMap(ma) {
_ match {
case Left(a) => m.pure(Left(a))
case Right(b) => f(b)
}
}
}
implicit def eitherMonad[A]: Monad[({ type λ[ɑ] = Either[A,ɑ] })#λ] =
eitherTMonad[A, ID]
}
Dependencies
Example
import Monad._
// TODO: Unnecessary with Scala 2.13.0-M5 (33478bd)
type RBE[A] = Either[Nothing, A]
println {
for {
x <- Right(6): RBE[Int]
y <- Right(7): RBE[Int]
z = x * y
} yield z // Right(42)
}