当生成的存在类型太复杂时,toList on shapeless HList 失败 [英] toList on shapeless HList fails when resulting existential type too complex

查看:25
本文介绍了当生成的存在类型太复杂时,toList on shapeless HList 失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

鉴于以下定义:

类 R[T]A级B级C级

这有效:

val s1 = new R[A] :: new R[B] :: HNilval r1 = s1.toList//r1 类型:List[R[_ >: A with B]]

虽然没有:

val s2 = new R[A] :: new R[B] :: new R[C] :: HNilval r2 = s2.toList//找不到参数 toList 的隐式值://shapeless.ToList[shapeless.::[R[A],//shapeless.::[R[B],shapeless.::[R[C],shapeless.HNil]]],Lub]

我期望的地方:

//r2 类型:List[R[_ >: A with B with C]]

伪解:

提供隐含的自己:

val r3 = s2.toList(ToList.hlistToList[R[A], R[B], ::[R[C], HNil],R[_ >: A 与 B 与 C]])

这当然不是解决方案,因为它消除了 HList 的全部好处(HList 由调用者连同所有必要的隐式提供).

澄清

如果我在最后得到一个没有类型界限的 List[R[_]] ,我会很高兴.

解决方案

您编写的代码应该按原样正常工作,生成您期望的精确存在类型.如果您针对 shapeless 打开一个错误,以便在下一个版本中不会忘记对此的修复,那将会非常有帮助.

与此同时,如果您真正想要的类型是 List[R[_]](这似乎对我更有用),那么您可以在比您的解决方法更简单的方法,

scala>进口无形._进口无形._标度>类 R[T] ;A级;乙级;C级定义类 R定义类 A定义的 B 类定义类 C标度>val s2 = new R[A] :: new R[B] :: new R[C] :: HNils2: R[A] :: R[B] :: R[C] :: HNil = R@7a26bc5e :: R@518fdf9 :: R@2bc9e90c :: HNil标度>s2.toList[R[_]]res0: List[R[_]] = List(R@7a26bc5e, R@518fdf9, R@2bc9e90c)

鉴于这种不太精确的类型可能在上下文中更有用,即使在修复了错误之后,您仍希望继续使用 toList 的显式元素类型参数,所以我认为这一点成为正确答案而不是解决方法.

Given the following definitions:

class R[T]

class A
class B
class C

This works:

val s1 = new R[A] :: new R[B] :: HNil
val r1 = s1.toList
// r1 of type: List[R[_ >: A with B]]

While this does not:

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]

Where I expect:

// r2 of type: List[R[_ >: A with B with C]]

Pseudo solution:

Supply implicit yourself:

val r3 = s2.toList(ToList.hlistToList[R[A], R[B], ::[R[C], HNil],
                                      R[_ >: A with B with C]])

This is of course not a solution, as it eliminates the whole benefit of HLists (the HList is supplied by a caller together with all necessary implicits).

Clarification

I am happy if I get a List[R[_]] at the end without the type bounds.

解决方案

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.

这篇关于当生成的存在类型太复杂时,toList on shapeless HList 失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆