有一些参数化的解决方法Poly
,另一个答案中提到了其中之一,尽管那里的确切实现不起作用。相反,你需要这样做:
import shapeless._, shapeless.poly.~>
val lists = List(1, 2) :: List("A", "B") :: List(1.1, 2.2) :: HNil
class sss(i: Int) extends (List ~> Set) {
def apply[T](l: List[T]): Set[T] = l.slice(i, i+1).toSet
}
object sss1 extends sss(1)
lists.map(sss1)
……事实是sss1
被定义为一个对象(不是val
) 对于最后一行的编译是必需的。
这种方法可以编译,但不可能在很多情况下使用它——例如你无法定义你的sss1
(或其他)方法中的对象,其中 hlist 的类型是通用的。
这是我之前使用过的稍微混乱但更灵活的解决方法:
import shapeless._
val lists = List(1, 2) :: List("A", "B") :: List(1.1, 2.2) :: HNil
object sss extends Poly2 {
implicit def withI[T]: Case.Aux[List[T], Int, Set[T]] =
at((l, i) => l.slice(i, i + 1).toSet)
}
lists.zipWith(lists.mapConst(1))(sss)
// Set(2) :: Set(B) :: Set(2.2) :: HNil
现在您实际上可以编写一个采用泛型的方法L <: HList
和切片参数i
-你只需要几个隐式参数来支持mapConst
and zipWith
应用程序。
不过,这两种方法都不是很优雅,我个人倾向于避免Poly
大多数情况下,定义自定义类型类几乎会更加简洁,并且在许多情况下是必需的。