Is there a way of having a unknown number of types for a generic method? I'm currently experimenting with the Scala Type System and could not find any solution to this.
Classic varargs for parameters look like this:
def printAll(strings: String*) {
strings.foreach(println)
}
But my question is, if there is something like that:
def magic[TYPES*](...) {
for(t <- TYPES){
typeOf[t] ...
}
}
edit: The idea was, to implement a way to create Lists in square brackets like this:
def magicList[A: TypeTag, B: TypeTag, C: TypeTag, D: TypeTag]: List[Any] = {
val a = typeOf[A] match { case ConstantType(a) => a.value }
val b = typeOf[B] match { case ConstantType(b) => b.value }
val c = typeOf[C] match { case ConstantType(c) => c.value }
val d = typeOf[D] match { case ConstantType(d) => d.value }
List(a,b,c,d)
}
magicList[1,2,3,4] == List(1,2,3,4)
I'm afraid you can't have [TYPES*]
in Scala.
If having [L <: HList]
(HList
is heterogeneous list) is enough for you then with Shapeless you can do
import shapeless.{::, HList, HNil, Poly0, Poly1, Witness}
import shapeless.ops.hlist.{FillWith, Mapper}
object witnessPoly extends Poly1 {
// implicit def cse[A](implicit witness: Witness.Aux[A]): Case.Aux[A, A] = at(_ => witness.value)
implicit def cse[A <: Singleton](implicit valueOf: ValueOf[A]): Case.Aux[A, A] = at(_ => valueOf.value) // scala 2.13
}
object nullPoly extends Poly0 {
implicit def default[A]: ProductCase.Aux[HNil, A] = at(null.asInstanceOf[A])
}
def magic[L <: HList](implicit
mapper: Mapper.Aux[witnessPoly.type, L, L],
fillWith: FillWith[nullPoly.type, L]
): L = mapper(fillWith())
magic[Witness.`1`.T :: Witness.`"a"`.T :: Witness.`true`.T :: HNil] // 1 :: a :: true :: HNil
magic[1 :: "a" :: true :: HNil] // scala 2.13 // 1 :: a :: true :: HNil
magic[1 :: 2 :: 3 :: 4 :: HNil] // scala 2.13 // 1 :: 2 :: 3 :: 4 :: HNil
Actually magic
can be defined even simpler
import shapeless.ops.hlist.Reify
def magic[L <: HList](implicit reify: Reify.Aux[L, L]): L = reify()