Anyway, here's my version:
trait MyOption[+A] {
import MyOption._
// single abstract method
def cata[X] (some: A => X, none: => X): X
def map[B] (f: A => B) =
cata(a => some(f(a)), none)
def flatMap[B] (f: A => MyOption[B]) =
cata(f, none)
def getOrElse[AA >: A] (e: => AA) = cata(a => a, e)
def filter (p: A => Boolean) =
cata(a => if (p(a)) this else none, this)
def foreach (f: A => Unit) { cata(f, ()) }
def isDefined = cata(_ => true, false)
def isEmpty = cata(_ => false, true)
// WARNING: not defined for None
def get = cata(a => a, error("MyOption.none.get"))
def orElse[AA >: A] (o: MyOption[AA]) =
cata(_ => this, o)
def toLeft[X] (right: => X) =
cata(a => Left(a), Right(right))
def toRight[X] (left: => X) =
cata(a => Right(a), Left(left))
def toList = cata(a => List(a), Nil)
def iterator =
cata(a => Iterator(a), Iterator.empty)
}
object MyOption {
def none[A] = new MyOption[A] {
def cata[X](s: A => X, n: => X) = n
}
def some[A](a: A) = new MyOption[A] {
def cata[X](s: A => X, n: => X) = s(a)
}
}
No comments:
Post a Comment