You can define your own type class to gather the evidence that the record has the fields you need:
import shapeless._, ops.record.Selector, record._, syntax.singleton._
val w1 = Witness("foo1")
val w2 = Witness("foo2")
val w3 = Witness("foo3")
case class HasMyFields[L <: HList](implicit
s1: Selector[L, w1.T, String],
s2: Selector[L, w2.T, Int],
s3: Selector[L, w3.T, Double]
)
object HasMyFields {
implicit def make[L <: HList](implicit
s1: Selector[L, w1.T, String],
s2: Selector[L, w2.T, Int],
s3: Selector[L, w3.T, Double]
) = HasMyFields[L]
}
And then, for example:
def fun1[L <: HList](xs: L)(implicit selectors: HasMyFields[L]) = {
import selectors._
(xs("foo1"), xs("foo2"), xs("foo3"))
}
It's still a little verbose, especially since the import is necessary, but much less so than requiring all of the selectors individually as implicit parameters.