Scala 无形状:typeclass中的递归调用

Scala 无形状:typeclass中的递归调用,scala,shapeless,Scala,Shapeless,在无形状类型类方法中实现递归调用的正确方法是什么 (早期警告:我正在学习变形,因此可能有一些明显的答案/备选方案我还不知道。非常感谢任何帮助!) 我有一个typeclass,它将case类转换为其他对象的嵌套结构,类似于中提到的ToMapRec示例并受其启发-除了返回一个可能递归的映射之外,它返回一个由可能递归的成员组成的case类。因此,与其转换MyType的实例,不如: trait GetsConverted case class MyType(someData: String, one:

在无形状类型类方法中实现递归调用的正确方法是什么

(早期警告:我正在学习变形,因此可能有一些明显的答案/备选方案我还不知道。非常感谢任何帮助!)

我有一个typeclass,它将case类转换为其他对象的嵌套结构,类似于中提到的
ToMapRec
示例并受其启发-除了返回一个可能递归的映射之外,它返回一个由可能递归的成员组成的case类。因此,与其转换
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)
在一个可能递归/嵌套的
映射[String,Any]
(如在另一个问题中一样)中,它返回类似以下内容的实例:

case class ReturnType(name: String, data: Option[Any], more: Set[ReturnType])
要创建
more
成员,似乎需要在type类中进行递归调用。但是在另一个方法内调用类型类的转换方法需要将该函数内所有类型的隐式参数线程化到最外层调用。因此,不是像这样的类型类转换:

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 = ???

通过下面的实现,我成功地获得了一些与您的示例相近的东西。 大部分内容与问题的答案相似。不同之处在于它转换为
ReturnType
,我还为
Coproduct
案例添加了几个案例(这是
密封特征的通用表示形式)

因此,使用以下代码:

val gen = LabelledGeneric[GetsConverted]
val m = MyType("someData", MyOtherType(AndSoOn(10)), MyOtherType(AndSoOn(20)))
val tmr = ToReturnTypeRec[gen.Repr]
val returnType = tmpr(gen.to(m))
你得到结果了吗

ReturnType(MyType,Some(someData),Set(
     ReturnType(MyOtherType,None,Set(
         ReturnType(,Some(20),Set())
     )),
     ReturnType(MyOtherType,None,Set(
         ReturnType(,Some(10),Set())
     ))
))
以下是实施方案:

trait ToReturnTypeRec[L] { def apply(l: L): ReturnType }

trait LowPriorityToReturnTypeRec {
implicit def hconsToReturnTypeRec1[K <: Symbol, V, T <: HList](implicit
    wit: Witness.Aux[K],
    tmrT: ToReturnTypeRec[T]
  ): ToReturnTypeRec[FieldType[K, V] :: T] = new ToReturnTypeRec[FieldType[K, V] :: T] {
    def apply(l: FieldType[K, V] :: T): ReturnType =
      tmrT(l.tail) match {
        case ReturnType(n,d,m) => ReturnType("", Some(l.head), m)
      }
  }
}

object ToReturnTypeRec extends LowPriorityToReturnTypeRec {
  def apply[T](implicit tmr: ToReturnTypeRec[T]) = tmr
  implicit val hnilToReturnTypeRec: ToReturnTypeRec[HNil] = new ToReturnTypeRec[HNil] {
    def apply(l: HNil): ReturnType = ReturnType("", None, Set())
  }

  implicit def hconsToReturnTypeRec0[K <: Symbol, V, T <: HList, R](implicit
    // wit: Witness.Aux[K],
    gen: LabelledGeneric.Aux[V, R],
    tmrH: Lazy[ToReturnTypeRec[R]],
    tmrT: ToReturnTypeRec[T]
  ): ToReturnTypeRec[FieldType[K, V] :: T] = new ToReturnTypeRec[FieldType[K, V] :: T] {
    def apply(l: FieldType[K, V] :: T): ReturnType =
      tmrT(l.tail) match {
        case ReturnType(n,d,m) => ReturnType(n, d, m + tmrH.value(gen.to(l.head)))
      }
  }

  implicit val cnillToReturnTypeRec: ToReturnTypeRec[CNil] = new ToReturnTypeRec[CNil] {
    def apply(c: CNil): ReturnType = ReturnType("Impossible", None, Set())
  }

  implicit def cconsToReturnTypeRec0[K <: Symbol, V <: Product, T <: Coproduct](implicit
    wit: Witness.Aux[K],
    tmrH: Lazy[ToReturnTypeRec[V]],
    tmrT: Lazy[ToReturnTypeRec[T]]
  ): ToReturnTypeRec[FieldType[K,V] :+: T] = new ToReturnTypeRec[FieldType[K, V] :+: T] {
    def apply(c: FieldType[K,V] :+: T): ReturnType = {
      c match {
        case Inl(h) => tmrH.value(h) match {
          case ReturnType(_,d,m) => ReturnType(wit.value.name, d, m)
        }
        case Inr(t) => tmrT.value(t)
      }
    }
  }

  implicit def genericToReturnTypeRec[P, R]( implicit
    gen: LabelledGeneric.Aux[P, R],
    tmr: Lazy[ToReturnTypeRec[R]]
  ): ToReturnTypeRec[P] = new ToReturnTypeRec[P] {
    def apply(p: P): ReturnType = tmr.value(gen.to(p))
  }
}
trait-ToReturnTypeRec[L]{def-apply(L:L):ReturnType}
性状低优先级返回类型REC{

implicit def hconsToReturnTypeRec1[K感谢您的努力!+1,但我可能没有很好地突出显示原始查询中需要递归的位置。这在我们都链接到的同一个问题中有很好的定义。但是当调用站点位于另一个(递归)内时,问题就会出现这样做一次很简单,但是如何递归调用:
val returnType=tmpr(gen.to(m))
ReturnType(MyType,Some(someData),Set(
     ReturnType(MyOtherType,None,Set(
         ReturnType(,Some(20),Set())
     )),
     ReturnType(MyOtherType,None,Set(
         ReturnType(,Some(10),Set())
     ))
))
trait ToReturnTypeRec[L] { def apply(l: L): ReturnType }

trait LowPriorityToReturnTypeRec {
implicit def hconsToReturnTypeRec1[K <: Symbol, V, T <: HList](implicit
    wit: Witness.Aux[K],
    tmrT: ToReturnTypeRec[T]
  ): ToReturnTypeRec[FieldType[K, V] :: T] = new ToReturnTypeRec[FieldType[K, V] :: T] {
    def apply(l: FieldType[K, V] :: T): ReturnType =
      tmrT(l.tail) match {
        case ReturnType(n,d,m) => ReturnType("", Some(l.head), m)
      }
  }
}

object ToReturnTypeRec extends LowPriorityToReturnTypeRec {
  def apply[T](implicit tmr: ToReturnTypeRec[T]) = tmr
  implicit val hnilToReturnTypeRec: ToReturnTypeRec[HNil] = new ToReturnTypeRec[HNil] {
    def apply(l: HNil): ReturnType = ReturnType("", None, Set())
  }

  implicit def hconsToReturnTypeRec0[K <: Symbol, V, T <: HList, R](implicit
    // wit: Witness.Aux[K],
    gen: LabelledGeneric.Aux[V, R],
    tmrH: Lazy[ToReturnTypeRec[R]],
    tmrT: ToReturnTypeRec[T]
  ): ToReturnTypeRec[FieldType[K, V] :: T] = new ToReturnTypeRec[FieldType[K, V] :: T] {
    def apply(l: FieldType[K, V] :: T): ReturnType =
      tmrT(l.tail) match {
        case ReturnType(n,d,m) => ReturnType(n, d, m + tmrH.value(gen.to(l.head)))
      }
  }

  implicit val cnillToReturnTypeRec: ToReturnTypeRec[CNil] = new ToReturnTypeRec[CNil] {
    def apply(c: CNil): ReturnType = ReturnType("Impossible", None, Set())
  }

  implicit def cconsToReturnTypeRec0[K <: Symbol, V <: Product, T <: Coproduct](implicit
    wit: Witness.Aux[K],
    tmrH: Lazy[ToReturnTypeRec[V]],
    tmrT: Lazy[ToReturnTypeRec[T]]
  ): ToReturnTypeRec[FieldType[K,V] :+: T] = new ToReturnTypeRec[FieldType[K, V] :+: T] {
    def apply(c: FieldType[K,V] :+: T): ReturnType = {
      c match {
        case Inl(h) => tmrH.value(h) match {
          case ReturnType(_,d,m) => ReturnType(wit.value.name, d, m)
        }
        case Inr(t) => tmrT.value(t)
      }
    }
  }

  implicit def genericToReturnTypeRec[P, R]( implicit
    gen: LabelledGeneric.Aux[P, R],
    tmr: Lazy[ToReturnTypeRec[R]]
  ): ToReturnTypeRec[P] = new ToReturnTypeRec[P] {
    def apply(p: P): ReturnType = tmr.value(gen.to(p))
  }
}