Last active
August 29, 2015 14:14
-
-
Save igstan/46607bf12c8922a11bca to your computer and use it in GitHub Desktop.
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
/* | |
* Assume you have a bunch of methods that return `Option` and you want to | |
* produce very precise output about which of those methods returned a `None` | |
* in case of "failure". | |
* | |
* There are a few strategies to doing that. Here are three of them: | |
*/ | |
object Main { | |
def foo: Option[String] = Some("foo") | |
def bar(x: String): Option[String] = None | |
def baz(y: String): Option[String] = Some(y) | |
def main(args: Array[String]): Unit = { | |
println(usingPatternMatching) | |
println(usingStandardOptionCombinators) | |
println(usingScalaz) | |
} | |
/* | |
* Using standard pattern matching on `Option`: | |
*/ | |
def usingPatternMatching: String = { | |
foo match { | |
case None => "missing foo" | |
case Some(a) => | |
if (a != "foo") { | |
"value not conforming" | |
} else { | |
bar(a) match { | |
case None => "missing bar" | |
case Some(b) => | |
baz(b) match { | |
case None => "missing baz" | |
case Some(c) => c | |
} | |
} | |
} | |
} | |
} | |
/* | |
* Using predefined combinators on `Option`: | |
*/ | |
def usingStandardOptionCombinators: String = { | |
foo.map { a => | |
if (a == "foo") { | |
bar(a).map { b => | |
baz(b) getOrElse "missing baz" | |
} getOrElse "missing bar" | |
} else "value not conforming" | |
} getOrElse "missing foo" | |
} | |
/* | |
* Using Scalaz extensions: | |
*/ | |
def usingScalaz: String = { | |
import scalaz.syntax.std.option._ | |
import scalaz.syntax.std.boolean._ | |
val r = for { | |
a <- foo \/> "missing foo" | |
b <- (a == "foo").option(a) \/> "value not conforming" | |
c <- bar(b) \/> "missing bar" | |
d <- baz(c) \/> "missing baz" | |
} yield d | |
r.merge | |
} | |
} |
@OleTraveler thanks! I really need to merge
the two cases of \/
. This was a contrived example, but I need the actual code to return an HTTP response, which would be 4XX for Left
and 2XX for Right
.
Also, I do indeed need the first missing one, because there's a data dependency between all the methods that return Option
, which is why I didn't use Validation
.
Sorry, I didn't RTFM at the top. What you have looks good.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'd suggest returning String/String from your methods where the Left or -/ side is the failure.
If you want all errors instead of the just the first missing one, use Validation and the applicative builder instead of a for comprehension.