Skip to content

Instantly share code, notes, and snippets.

@luciferous
Created June 27, 2014 08:15
Show Gist options
  • Save luciferous/2b6630b6b72538256ceb to your computer and use it in GitHub Desktop.
Save luciferous/2b6630b6b72538256ceb to your computer and use it in GitHub Desktop.
Church encoding of Option

Regular Option

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

implicit def optionMonad[A](o: Option[A]) =
  new MonadOps[A] {
    def flatMap[B](f: A => Option[B]) = o match {
      case None => None
      case Some(x) => f(x)
    }
    def map[B](f: A => B) = flatMap(f andThen Some)
  }

Church encoding of Option

// type OptionC[A] = forall B. B => (A => B) => B
trait OptionC[+A] {
  def mk[B]: B => (A => B) =>B
}

def some[A](a: A) = new OptionC[A] { def mk[B] = n => s => s(a) }
def none[A]       = new OptionC[A] { def mk[B] = n => _ => n }

implicit def optionCMonad[A](option: Maybe[A]) =
  new MonadOps[Maybe, A] {
    def flatMap[B](f: A => Maybe[B]) =
      new Maybe[B] {
        def mk[B] = n => s => {
          option.mk(n) { a => f(a).mk(n)(s) }
        }
      }
    def map[B](f: A => B): Maybe[B] = flatMap(f andThen some)
  }

Usage

Add 1 and 2.

> val x = for (a <- some(1); b <- some(2)) yield a + b
> x.mk()(println)
3

Short circuit on none.

> val y = for (a <- none[Int]; b <- some(2)) yield a + b
> x.mk(println("nothing"))(println)
nothing
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment