好的,我想我找到了答案。初步测试似乎确认了这一点。
scala> :paste
import shapeless._
import shapeless.ops.hlist.At
import shapeless.syntax.std.tuple._
final class myHListOps[L <: HList](l: L) {
import hlistaux._
def extractors(implicit extractor : Extractor[_0, L,L]) : extractor.Out = extractor()
}
object hlistaux {
trait Extractor[HF<:Nat, In <: HList, Remaining<: HList] extends DepFn0 { type Out <: HList }
object Extractor {
def apply[HL <: HList]
(implicit extractor: Extractor[_0, HL,HL]):
Aux[_0, HL, HL, extractor.Out] = extractor
type Aux[HF<:Nat, In <: HList, Remaining<: HList, Out0 <: HList] = Extractor[HF, In, Remaining] { type Out = Out0 }
implicit def hnilExtractor: Aux[_0, HNil, HNil, HNil] =
new Extractor[_0, HNil, HNil] {
type Out = HNil
def apply(): Out = HNil
}
implicit def hSingleExtractor1[N<:Nat, In<:HList, H ]
(implicit att : At[In, N]): Aux[N, In, H::HNil, At[In,N]::HNil] =
new Extractor[N, In, H::HNil] {
type Out = At[In,N]::HNil
def apply(): Out = att::HNil
}
implicit def hlistExtractor1[N <: Nat, In<:HList, H, Tail<: HList]
(implicit mt : Extractor[Succ[N], In, Tail],
att : At[In, N])
:Aux[N, In, H::Tail, At[In,N]::mt.Out] = {
new Extractor[N, In, H::Tail] {
type Out = At[In,N]::mt.Out
def apply(): Out = {
att :: mt()
}
}
}
}
}
import shapeless._
import shapeless.ops.hlist.At
import shapeless.syntax.std.tuple._
defined class myHListOps
defined object hlistaux
scala> val l = "Hello"::HNil
l: shapeless.::[String,shapeless.HNil] = Hello :: HNil
scala> val lo = new myHListOps(l).extractors
lo: shapeless.::[shapeless.ops.hlist.At[shapeless.::[String,shapeless.HNil],shapeless._0],shapeless.HNil] = shapeless.ops.hlist$At$$anon$54@12d33d1c :: HNil
scala> lo.head(l)
res0: lo.head.Out = Hello
scala> val m = 42::l
m: shapeless.::[Int,shapeless.::[String,shapeless.HNil]] = 42 :: Hello :: HNil
scala> val mo = new myHListOps(m).extractors
mo: shapeless.::[shapeless.ops.hlist.At[shapeless.::[Int,shapeless.::[String,shapeless.HNil]],shapeless._0],shapeless.::[shapeless.ops.hlist.At[shapeless.::[Int,shapeless.::[String,shapeless.HNil]],shapeless.Succ[shapeless._0]],shapeless.HNil]] = shapeless.ops.hlist$At$$anon$54@5e181eeb :: shapeless.ops.hlist$At$$anon$55@1960690 :: HNil
scala> mo.head(m)
res3: mo.head.Out = 42
scala> mo.tail.head(m)
res4: mo.tail.head.Out = Hello