【发布时间】:2016-10-02 22:02:33
【问题描述】:
我有以下方法:
import shapeless._
import shapeless.UnaryTCConstraint._
def method[L <: HList : *->*[Seq]#λ](list: L) = println("checks")
它让我可以确保发生以下情况:
val multipleTypes = "abc" :: 1 :: 5.5 :: HNil
val onlyLists = Seq("abc") :: Seq(1) :: Seq(5.5) :: HNil
method(multipleTypes) // throws could not find implicit value ...
method(onlyList) // prints checks
如何使用另一个参数列表来扩充method,例如:
def method2[L <: HList : *->*[Seq]#λ, M <: HList](list: L)(builder: M => String) = println("checks")
但是有一个限制,HList M 必须和 HList L 的大小相同,并且只包含 HList L 的内部类型的元素。让我举个例子:
// This should work
method2(Seq("abc") :: Seq(1) :: Seq(5.5) :: HNil){
case a :: 1 :: d :: HNil => "works"
}
// This should throw some error at compile time, because the second element is Seq[Int]
// therefore in the builder function I would like the second element to be of type Int.
method2(Seq("abc") :: Seq(1) :: Seq(5.5) :: HNil){
case a :: true :: d :: HNil => "fails"
}
// This should also fail because the HLists are not of the same length.
method2(Seq("abc") :: Seq(1) :: Seq(5.5) :: HNil){
case 1 :: d :: HNil => "fails"
}
如果我这样定义method2:
def method2[L <: HList : *->*[Seq]#λ](list: L)(builder: L => String) = println("checks")
它几乎解决了这个问题,唯一缺少的是构建器将具有 Seq[T] 类型的元素而不是 T 类型的元素。
【问题讨论】:
-
method2(Seq("abc", "def") :: Seq(1,2,3) :: Seq(5.5) :: HNil) { case a :: b :: c :: HNil => a.toString + b.toString + c.toString }的结果应该是什么? -
它应该可以工作,因为 HList 的大小相同,并且您对 a、b 和 c 的类型没有限制,因此应该正确推断它们为
String、Int和Double。