I am writing an internal DSL, and am using Shapeless to enforce type safety. However, I have got stuck with an issue.
The simplified version of the problem is as follows.
Consider the code snippet below:
import shapeless._
import syntax.std.function._
import ops.function._
implicit class Ops[P <: Product, L <: HList](p: P)(implicit val gen: Generic.Aux[P, L]) {
def ~|>[F, R](f: F)(implicit fp: FnToProduct.Aux[F, L ⇒ R]) =
f.toProduct(gen.to(p))
}
(1, 2) ~|> ((x: Int, y: Int) ⇒ x + y) // -> at compile time, it ensures the types are aligned.
(1, 2, 3) ~|> ((x: Int, y: Int, z: Int) ⇒ x + y + z) // -> compiles okay
(1, "2", 3) ~|> ((x: Int, y: Int, z: Int) ⇒ x + y + z) // -> gives a compile error, as expected.
However, instead of A, I would like to use a container type Place[A].
case class Place[A](a: A)
val a = Place[Int](1)
val b = Place[Int]("str")
and also ensures the types are aligned with respect to the type parameters.
(a, b) ~|> ((x: Int, y: String) ⇒ x.toString + y)
That is, in the above case, I would like the types to be checked based on the type parameter of Place[_], which in the above case, Int and String respectively.
I highly appreciate your help!