0
votes

I know the type of an HList and I would like to apply a specific function to each of the specific items in the HList. For example.

I know the type of the HList, in this case String :: Int :: String :: HNil

val values = "Hello World" :: 5 :: "Goodbye World" :: HNil

So I create a function from type => Int for each item.

val funcs =
  ((_: String) => 1) ::
  ((_: Int) => 2) ::
  ((_: String) => 3) ::
   HNil

I want to apply function 1 to value 1, function 2 to value 2, etc for each item in the list. This is the best guess at what the function signature might look. V

// V are the Values of type String :: Int :: String :: HNil
// F are the Functions of type (String => Int) :: (Int => Int) :: (String => Int) :: HNil
// R is the Int Results of type Int :: Int :: Int :: HNil
def applyFunction[V <: HList, F <: HList, R <: HList](v: V, f: F)(
   implicit ev: V =:= F,
   utcc: UnaryTCConstraint[F, Function[*, Int]]
): R

Now I'm struggling with how to actually implement this function or if maybe Shapeless already has something that does this already.

2

2 Answers

1
votes

You can use standard type class shapeless.ops.hlist.ZipApply

funcs.zipApply(values) // 1 :: 2 :: 3 :: HNil
3
votes

Using this SO answer as an inspiration, I came up with the following:

import shapeless._

val values = "Hello World" :: 5 :: "Goodbye World" :: HNil

val funcs = ((_: String) => 1) ::
            ((_: Int) => 2) ::
            ((_: String) => 3) :: HNil

object applyTo extends Poly1 {
  implicit def caseInt = at[(Int=>Int,Int)]      {case (f,v) => f(v)}
  implicit def caseStr = at[(String=>Int,String)]{case (f,v) => f(v)}
}

funcs.zip(values).map(applyTo)
//1 :: 2 :: 3 :: HNil: Int :: Int :: Int :: shapeless.HNil