Maybe

Implementation

sealed trait Maybe[+A]
case class Some[A](head: A) extends Maybe[A]
case object None extends Maybe[Nothing]

object Maybe {

  implicit def maybeTMonad[M[_]: Monad]: Monad[({ type λ[ɑ] = M[Maybe[ɑ]] })#λ] =
    new Monad[({ type λ[ɑ] = M[Maybe[ɑ]] })#λ] {

      private lazy val m: Monad[M] = implicitly[Monad[M]]

      def pure[A](a: A): M[Maybe[A]] =
        if (a == null) m.pure(None) else m.pure(Some(a))

      def flatMap[A, B](ma: M[Maybe[A]])(f: A => M[Maybe[B]]): M[Maybe[B]] =
        m.flatMap(ma) {
          _ match {
            case Some(a) => f(a)
            case None    => m.pure(None)
          }
        }
    }

  implicit val maybeMonad: Monad[Maybe] = maybeTMonad[ID]

}

Dependencies

Example

import Monad._

println {
  for {
    x <- Some(6): Maybe[Int]
    y <- Some(7): Maybe[Int]
    z  = x * y
  } yield z // Some(42)
}

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/maybe.md |
  codedown scala | xargs -0 scala -nc -e
Some(42)