Either

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._

println {
  for {
    x <- Right(6): Either[Nothing, Int] // requires Scala 2.13 (33478bd)
    y <- Right(7): Either[Nothing, Int]
    z  = x * y
  } yield z // Right(42)
}

References

Demo

This file is literate Scala, and can be run using Codedown:

$ curl -s \
  https://earldouglas.com/posts/type-classes/applicative.md \
  https://earldouglas.com/posts/type-classes/functor.md \
  https://earldouglas.com/posts/type-classes/id.md \
  https://earldouglas.com/posts/type-classes/monad.md \
  https://earldouglas.com/posts/type-classes/either.md |
  codedown scala | xargs -0 scala -nc -e
Right(42)