当生成的存在类型过于复杂时,无形HList上的toList失败

时间:2013-05-23 00:01:30

标签: scala shapeless

鉴于以下定义:

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[_]],我很高兴。

2 个答案:

答案 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]])。