Skip to content

Instantly share code, notes, and snippets.

@devlaam
Last active July 4, 2018 20:09
Show Gist options
  • Save devlaam/bdce0b64fe3c03254a481309a86dfd43 to your computer and use it in GitHub Desktop.
Save devlaam/bdce0b64fe3c03254a481309a86dfd43 to your computer and use it in GitHub Desktop.
Handling nested contexts in Scala, a monad transformer done by hand.
/**
* Helper class to use future-options in for-comprehension-loops
* Use this class as a combined future/option so handling becomes more easy on these
* objects. Any empty options will short-circuit the future chain and any exceptions
* in a future will result in a future-none result.
* Available under MIT license.
*/
case class Maybe[+A](val maybe: Future[Option[A]]) extends AnyVal
{ import scala.util.control.NonFatal
def value = maybe.recoverWith{ case NonFatal(_) => Maybe.never }
def flatMap[B](f: A => Maybe[B]): Maybe[B] =
{ val newMaybe = value.flatMap
{ case Some(a) => f(a).value
case None => Maybe.never }
Maybe(newMaybe) }
def map[B](f: A => B): Maybe[B] =
{ Maybe(value.map(opt => opt map f)) }
def filter(p: A => Boolean): Maybe[A] =
{ val newMaybe = value.map
{ case Some(a) if (p(a)) => Some(a)
case _ => None }
Maybe(newMaybe) }
final def withFilter(p: A => Boolean) = filter(p)
def getOrElse[B >: A](dflt: B) = value.map(_.getOrElse(dflt))
def isDefined: Future[Boolean] = value.map(_.isDefined) }
object Maybe
{ val never = Future.successful(None)
def apply[B](opt: Option[B]) = new Maybe(Future.successful(opt))
def apply[B](fut: Future[B])(implicit d: DummyImplicit) = new Maybe(fut.map(b => Option(b))) }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment