鉴于以下定义:
class R[T]
class A
class B
class C
这有效:
val s1 = new R[A] :: new R[B] :: HNil
val r1 = s1.toList
// r1 of type: List[R[_ >: A with B]]
虽然这不是:
val s2 = new R[A] :: new R[B] :: new R[C] :: HNil
val r2 = s2.toList
// could not find implicit value for parameter toList:
// shapeless.ToList[shapeless.::[R[A],
// shapeless.::[R[B],shapeless.::[R[C],shapeless.HNil]]],Lub]
我期待的地方:
// r2 of type: List[R[_ >: A with B with C]]
伪解决方案:
自己暗示:
val r3 = s2.toList(ToList.hlistToList[R[A], R[B], ::[R[C], HNil],
R[_ >: A with B with C]])
这当然不是一个解决方案,因为它消除了HLists
的全部好处(HList
由调用者提供以及所有必要的含义。)
澄清
如果我在没有类型界限的情况下得到List[R[_]]
,我很高兴。
答案 0 :(得分:4)
你写的代码应该是Just Work,原样,产生你期望的精确存在类型。如果你打开一个无形的bug就会非常有用,这样下一个版本就不会忘记修复它。
与此同时,如果您真正关注的类型是List[R[_]]
(这对我来说似乎更有用),那么您可以以比解决方法更简单的方式明确地要求它,
scala> import shapeless._
import shapeless._
scala> class R[T] ; class A ; class B ; class C
defined class R
defined class A
defined class B
defined class C
scala> val s2 = new R[A] :: new R[B] :: new R[C] :: HNil
s2: R[A] :: R[B] :: R[C] :: HNil = R@7a26bc5e :: R@518fdf9 :: R@2bc9e90c :: HNil
scala> s2.toList[R[_]]
res0: List[R[_]] = List(R@7a26bc5e, R@518fdf9, R@2bc9e90c)
鉴于这种不太精确的类型在上下文中可能更有用,即使修复了错误,你仍然希望继续使用toList
的显式元素类型参数,所以我认为这是正确答案而不是解决方法。
答案 1 :(得分:0)
我刚刚提交了PR来解决此问题。
只是在没有明确指定类型的情况下调用s2.toList
,应该返回与创建具有相同项目的(标准)列表相同的类型,并让scalac为您推断列表的类型(这是某种东西)比如List[R[_ >: A with B with C]]
)。