Last active
September 26, 2018 06:34
-
-
Save danslapman/90e7291c5f55047dbcf2dcac7b422344 to your computer and use it in GitHub Desktop.
Combine two partial functions narrowing domain
This file contains hidden or 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
import scala.util.{Success, Try} | |
val pf1: PartialFunction[Try[String], String] = { | |
case Success(s) => s | |
} | |
val pf2: PartialFunction[String, String] = { | |
case s if s.contains("pass") => s | |
} | |
class Combined[-A, B, +C] (pf: PartialFunction[A, B], k: PartialFunction[B, C]) extends PartialFunction[A, C] with Serializable { | |
import Combined._ | |
def isDefinedAt(x: A) = { | |
val b: B = pf.applyOrElse(x, checkFallback[B]) | |
if (!fallbackOccurred(b)) k.isDefinedAt(b) else false | |
} | |
def apply(x: A): C = k(pf(x)) | |
override def applyOrElse[A1 <: A, B1 >: C](x: A1, default: A1 => B1) = { | |
val pfv = pf.applyOrElse(x, checkFallback[B]) | |
if (!fallbackOccurred(pfv)) k.applyOrElse(pfv, (_: B) => default(x)) else default(x) | |
} | |
} | |
object Combined { | |
private[this] val fallback_pf: PartialFunction[Any, Any] = { case _ => fallback_pf } | |
private def checkFallback[B] = fallback_pf.asInstanceOf[PartialFunction[Any, B]] | |
private def fallbackOccurred[B](x: B) = fallback_pf eq x.asInstanceOf[AnyRef] | |
} | |
implicit class PartialFunctionCombine[A, B](pf: PartialFunction[A, B]) { | |
def combine[C](pf2: PartialFunction[B, C]): Combined[A, B, C] = new Combined(pf, pf2) | |
} | |
val pf = pf1 combine pf2 | |
println(pf.applyOrElse(Try("reject"), (_: Try[String]) => "not defined")) | |
println(pf.applyOrElse(Try("pass"), (_: Try[String]) => "not defined")) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment