Skip to content

Instantly share code, notes, and snippets.

@tomverran
Created December 16, 2016 09:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomverran/46a58fd51073be1e272dccfccf68423f to your computer and use it in GitHub Desktop.
Save tomverran/46a58fd51073be1e272dccfccf68423f to your computer and use it in GitHub Desktop.
Nested either value extraction
type NestedEither = Either[Either[String, Int], Double]
val foo: NestedEither = Left(Right(5))
sealed trait Extractor[H, N] {
def value(a: H): Option[N]
}
implicit def FoundExtractor[A] = new Extractor[A, A] {
def value(a: A) = Some(a)
}
implicit def GoLeftExtractor[A, B, N](implicit e: Extractor[A, N]) = new Extractor[Either[A, B], N] {
def value(a: Either[A, B]) = a.left.toOption.flatMap(e.value)
}
implicit def GoRightExtractor[A, B, N](implicit e: Extractor[B, N]) = new Extractor[Either[A, B], N] {
def value(a: Either[A, B]) = a.right.toOption.flatMap(e.value)
}
implicit class Extractable[H](h: H) {
def find[B](implicit e: Extractor[H, B]) = e.value(h)
}
foo.find[Double] //None
foo.find[Int] //Some(5)
foo.find[String] // None
// foo.as[Float] won't compile as NestedEither does not contain float
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment