【发布时间】:2017-01-13 01:39:03
【问题描述】:
在无形类型类方法中实现递归调用的正确方法是什么?
(早期警告:我正在学习无形,所以可能有我还不知道的明显答案/替代方案。非常感谢任何帮助!)
我有一个类型类,它将一个案例类转换为其他对象的嵌套结构——类似于this stackoverflow question 中提到的ToMapRec 示例并受到其启发——除了返回潜在递归 Map 之外,它返回一个由潜在递归成员组成的案例类。所以不要转换MyType的实例:
trait GetsConverted
case class MyType(someData: String, one: GetsConverted, other: GetsConverted) extends GetsConverted
case class MyOtherType(blah: AndSoOn) extends GetsConverted
case class AndSoOn(eventualFinalValue: Int)
进入一个可能递归/嵌套的Map[String,Any](如在另一个问题中),它返回类似于以下实例的内容:
case class ReturnType(name: String, data: Option[Any], more: Set[ReturnType])
要创建more 成员似乎需要在类型类中进行递归调用。但是在另一个方法内部调用类型类的转换方法需要将该函数内部所有类型的隐式参数线程化到最外层调用。因此,而不是像这样的类型类转换:
implicit def hconsToMapRec0[K, V, A <: HList, B <: HList](implicit
wit: Witness.Aux[K],
gen: LabelledGeneric.Aux[V, R],
tmrH: Lazy[ToMapRec[A]],
tmrT: Lazy[ToMapRec[B]]
): ReturnType = ???
深度三方法(我猜)需要一个函数签名,例如:
implicit def hconsToMapRec0[K, V, A <: HList, B <: HList, W, C <: HList, D <: HList, X, E <: HList, F <: HList](implicit
wit: Witness.Aux[K],
gen0: LabelledGeneric.Aux[V, A],
tmrH0: Lazy[ToMapRec[A]],
tmrT0: Lazy[ToMapRec[B]],
gen1: LabelledGeneric.Aux[W, C],
tmrH1: Lazy[ToMapRec[C]],
tmrT1: Lazy[ToMapRec[D]],
gen2: LabelledGeneric.Aux[X, E],
tmrH2: Lazy[ToMapRec[E]],
tmrT2: Lazy[ToMapRec[F]]
): ReturnType = ???
或者可能更糟。一般来说,这种方法需要一种方法,该方法的隐含参数乘以递归中尽可能多的深度。并且深度级别的数量仅在运行时才知道。所以这不可能是这样做的。
这感觉类似于 scala 集合库中硬编码的 22 元方法。由于 Shapeless 存在的理由是抽象超过 arity,这似乎是一个问题,需要我迄今为止学到的更多 Shapeless-foo。
所以问题是:你将如何编写一个无形类型类来将任意案例类的结构类似于上面的 MyType 示例转换为递归定义的值,例如:
ReturnType("MyType", Some("someData"), Set(
ReturnType("MyOtherType", None, Set(
ReturnType("AndSoOn", Some(10), Set())
)),
ReturnType("MyOtherType", None, Set(
ReturnType("AndSoOn", Some(20), Set())
))
))
【问题讨论】: