Yes, you can
import shapeless._ import shapeless.ops.traversable._ import syntax.std.traversable._ import ops.function._ def fromList[F, I <: HList, O](f: F)(implicit ftp: FnToProduct.Aux[F, I => O], ft: shapeless.ops.traversable.FromTraversable[I]): List[Int] => Option[O] = { x: List[Int] => x.toHList[I].map(ftp(f)) }
Explanation
We use FnToProduct to convert any FunctionN to Function1 , which takes an HList as an argument.
So,
Int => String ----> Int :: HNil => String (Int, Int) => String ----> Int :: Int :: HNil => String ...
Now that we have abstracted from the arity of the input parameters for the function, we can simply convert List[Int] to an HList , which is suitable for inputting the converted function. To perform this conversion, we need FromTraversable[I] in the scope.
If everything succeeds, we will return and Option[O] , where O is the return type of the function. If the List entry is in the wrong shape, we just don't return None .
Using
@ val f1: Int => String = _.toString f1: Int => String = <function1> @ val f2: (Int, Int) => String = (_, _).toString f2: (Int, Int) => String = <function2> @ val fromList1 = fromList(f1) fromList1: List[Int] => Option[String] = <function1> @ val fromList2 = fromList(f2) fromList2: List[Int] => Option[String] = <function1> @ fromList1(List(1)) res22: Option[String] = Some(1) @ fromList2(List(1, 2)) res23: Option[String] = Some((1,2)) @ fromList1(List()) res24: Option[String] = None
source share