4

给定以下定义:

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]])

这当然不是一个解决方案,因为它消除了HListsHList由调用者提供以及所有必要的隐含)的全部好处。

澄清

List[R[_]]如果最后得到没有类型限制的a,我会很高兴。

4

2 回答 2

4

The code you've written ought to Just Work, as-is, producing the precise existential type that you were expecting. It'd be very helpful if you would open a bug against shapeless so that a fix for this doesn't get forgotten for the next release.

In the meantime, if the type you're really after is List[R[_]] (which seems more likely to be useful to me) then you can ask for it explicitly in a much simpler way than your workaround,

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)

Given that this less precise type is likely to be more useful in context, you'll want to continue using the explicit element type argument to toList even after the bug is fixed, so I consider this to be the right answer rather than a workaround.

于 2013-05-24T09:12:18.203 回答
0

我刚刚提交了一个PR来解决这个问题。

只需调用s2.toList,而不显式指定类型,应该返回与创建具有相同项目的(标准)列表相同的类型,并让 scalac 为您推断列表的类型(类似于List[R[_ >: A with B with C]])。

于 2014-06-06T19:38:26.280 回答