Last active
September 9, 2017 15:55
-
-
Save logicalguess/8ff8f0fd2204884101fbb73989aa46d9 to your computer and use it in GitHub Desktop.
combining functions into a PartialFunction
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
| package logicalguess | |
| import shapeless.HList._ | |
| import shapeless._ | |
| import scala.annotation.implicitNotFound | |
| import scala.language.implicitConversions | |
| import scala.reflect.ClassTag | |
| object ShapelessFunctions { | |
| // trait PfConverter[I, O, L <: HList] extends DepFn1[L] with Serializable { | |
| // type Out = PartialFunction[I, O] | |
| // } | |
| trait PfConverter[I, O, L <: HList] extends Function1[L, PartialFunction[I, O]] with Serializable | |
| implicit def pfConv1[H1, H2, T <: HList](implicit tailConv: PfConverter[Any, Any, T], tag: ClassTag[H1]): PfConverter[Any, Any, (H1 => H2) :: T] = | |
| new PfConverter[Any, Any, (H1 => H2) :: T] { | |
| def apply(l: (H1 => H2) :: T): PartialFunction[Any, Any] = { | |
| val pf: PartialFunction[Any, Any] = { | |
| case i: H1 => | |
| l.head(i) | |
| } | |
| pf.orElse(tailConv(l.tail)) | |
| } | |
| } | |
| implicit def emptyPfC[I, O]: PfConverter[I, O, HNil] = | |
| new PfConverter[I, O, HNil] { | |
| def apply(n: HNil) = Map.empty[I, O] | |
| } | |
| implicit def convertToPf[I, O, L <: HList](in: L)(implicit converter: PfConverter[I, O, L]) = converter(in) | |
| @implicitNotFound("No function of type ''${I} => ${O}'' found in shape ${L}.") | |
| trait ShapeWitness[L <: HList, I, O] extends Function2[L, I, O] with Serializable | |
| // trait ShapeWitness[L <: HList, I, O] extends DepFn2[L, I] with Serializable { | |
| // type In = I | |
| // type Out = O | |
| // } | |
| object ShapeWitness { | |
| implicit def witness[H1, H2, T <: HList]: ShapeWitness[(H1 => H2) :: T, H1, H2] = | |
| new ShapeWitness[(H1 => H2) :: T, H1, H2] { | |
| def apply(l: (H1 => H2) :: T, i: H1) = l.head(i) | |
| } | |
| implicit def recurse[H, T <: HList, I, O](implicit p: ShapeWitness[T, I, O]): ShapeWitness[H :: T, I, O] = | |
| new ShapeWitness[H :: T, I, O] { | |
| def apply(l: H :: T, i: I) = p(l.tail, i) | |
| } | |
| } | |
| def apply[I, O, L <: HList](pf: PartialFunction[Any, Any], in: I)(implicit witness: ShapeWitness[L, I, O]): O = { | |
| pf(in).asInstanceOf[O] | |
| } | |
| case class Input(value: String) | |
| case class Output(value: String) | |
| def main(args: Array[String]): Unit = { | |
| // type L = (String => Int) :: (Input => Output) :: HNil | |
| // val functionList: L = ((s: String) => s.length) :: ((c: Input) => Output(c.value)) :: HNil | |
| // val pf: PartialFunction[Any, Any] = convertToPf(functionList) | |
| val pf: PartialFunction[Any, Any] = ((s: String) => s.length) :: ((c: Input) => Output(c.value)) :: HNil | |
| val res0: Output = apply(pf, Input("hi")) | |
| println(res0 + ": " + res0.getClass) | |
| // Output(hi): class logicalguess.ShapelessFunctions$Output | |
| val res1 = pf(Input("hi")) | |
| println(res1 + ": " + res1.getClass) | |
| // Output(hi): class logicalguess.ShapelessFunctions$Output | |
| val res2: Int = apply(pf, "abc") | |
| println(res2 + ": " + res2.getClass) | |
| // 3: int | |
| val res3 = pf("abc") | |
| println(res3 + ": " + res3.getClass) | |
| // 3: class java.lang.Integer | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment