I ask this question, because i found myself needing functionality similar to andThen of normal function (but still conforming to semantics of partial function). What i mean should be explained by the following:
andThen for functions:
val x: Int => Int = ???
val y: Int => Double = ???
val z: Int => Double = x andThen y
andThen for partial function (named differently because andThen already exist with different semantics):
val x: PartialFunction[A, B] = ???
val y: PartialFunction[B, C] = ???
val z: PartialFunction[A, C] = x andThenExtact y
Where z is defined on parameter a: A which has the following properties:
x is defined at a
y is defined at x(a)
I have came up with the following extension that should in principle provide the desired functionality:
type =>?[-A, +B] = PartialFunction[A, B]
class RichPartialFunction[A, B](private val lhs: A =>? B) extends AnyVal {
def andThenWiden[BB >: B, R](widening: BB =>? R): A =>? R = {
val InnerMatcher = matchArgument(lhs)
val pf: A =>? R = {
case InnerMatcher(res) if widening.isDefinedAt(res) =>
widening(res)
}
pf
}
def andThenExact[R](pipeTo: B =>? R): A =>? R = {
val InnerMatcher = matchArgument(lhs)
val pf: A =>? R = {
case InnerMatcher(res) if pipeTo.isDefinedAt(res) =>
pipeTo(res)
}
pf
}
}
private def matchArgument[A, B](fun: A =>? B): PartiallyUnapply[A, B] = new PartiallyUnapply(fun)
private class PartiallyUnapply[A, B](private val fun: A =>? B) extends AnyVal {
def unapply(arg: A): Option[B] = {
fun.andThen(Some(_)).applyOrElse(arg, (_: A) => None)
}
}
My question is there better solution for this problem, and if my approach is bad then how could i replace x andThenExtact y in my code?