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]] =
.pure(Right(b))
m
def flatMap[B, C](ma: M[Either[A, B]])(f: B => M[Either[A, C]]): M[Either[A, C]] =
.flatMap(ma) {
mmatch {
_ case Left(a) => m.pure(Left(a))
case Right(b) => f(b)
}
}
}
implicit def eitherMonad[A]: Monad[({ type λ[ɑ] = Either[A,ɑ] })#λ] =
[A, ID]
eitherTMonad
}
import Monad._
{
println for {
<- Right(6): Either[Nothing, Int] // requires Scala 2.13 (33478bd)
x <- Right(7): Either[Nothing, Int]
y = x * y
z } yield z // Right(42)
}
This file is literate Scala, and can be run using Codedown:
$ curl \
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)