Last active
July 4, 2018 20:09
-
-
Save devlaam/bdce0b64fe3c03254a481309a86dfd43 to your computer and use it in GitHub Desktop.
Handling nested contexts in Scala, a monad transformer done by hand.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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