Skip to content

Instantly share code, notes, and snippets.

@halcat0x15a
Created April 13, 2013 04:57
Show Gist options
  • Save halcat0x15a/5376994 to your computer and use it in GitHub Desktop.
Save halcat0x15a/5376994 to your computer and use it in GitHub Desktop.
Maybe Monad with Church Encoding in Scala
import scala.language.higherKinds
import scala.language.implicitConversions
import scala.language.reflectiveCalls
trait Forall[M[_]] {
def apply[A]: M[A]
}
object Maybe {
type Maybe[A] = Forall[({ type F[R] = (A => R, => R) => R })#F]
implicit def ops[A](m: Maybe[A]) = new {
def map[B](f: A => B): Maybe[B] = bind(point[B]_ compose f)(m)
def flatMap[B](f: A => Maybe[B]): Maybe[B] = bind(f)(m)
}
def point[A](a: A): Maybe[A] =
new Forall[({ type F[R] = (A => R, => R) => R })#F] {
def apply[R]: (A => R, => R) => R = (f, r) => f(a)
}
def bind[A, B](f: A => Maybe[B])(m: Maybe[A]): Maybe[B] =
new Forall[({ type F[R] = (B => R, => R) => R })#F] {
def apply[R]: (B => R, => R) => R =
(g, r) => m[R](a => f(a)[R](g, r), r)
}
def empty[A]: Maybe[A] =
new Forall[({ type F[R] = (A => R, => R) => R })#F] {
def apply[R]: (A => R, => R) => R = (f, r) => r
}
def run[A](a: A)(m: Maybe[A]): A = m[A](x => x, a)
}
object Main extends App {
import Maybe._
def get[K, V](k: K)(m: Map[K, V]): Maybe[V] =
m get k map point[V] getOrElse empty[V]
val foobar = Map('foo -> 2, 'bar -> 3)
println(run(-1)(for {
m <- get('foo)(foobar)
n <- get('bar)(foobar)
} yield m + n))
println(run(-1)(for {
m <- get('baz)(foobar)
n <- get('bar)(foobar)
} yield m + n))
}
@xuwei-k
Copy link

xuwei-k commented Apr 13, 2013

  implicit class ops[A](val m: Maybe[A]) extends AnyVal{
    def map[B](f: A => B): Maybe[B] = bind(point[B]_ compose f)(m)
    def flatMap[B](f: A => Maybe[B]): Maybe[B] = bind(f)(m)
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment