2

我有以下课程;

trait Part

case class Part1() extends Part

case class Part2() extends Part

case class Part3(part1: Part1, part2: Part2) extends Part

case class Part4(part1: Part1, part2: Option[Part2], part3: List[Part3]) extends Part

case class Part5(name: String, part4: Part4) extends Part

我将Part1和归类Part2为简单的部分和,Part3以及Part4“组合部分”,因为它们仅由其他部分或其他部分的某些效果组成。

我希望能够将分组的部件转换为部件列表,反之亦然。但我只想使用两种方法来做到这一点。一个用于分组部分到列表,一个用于列表到分组部分,因为我有数百个扩展类,Part我不想为所有这些类编写方法。

我设法将分组部分转换为列表如下;

type IsParts[x] <: Boolean = x match {
  case Part => true
  case List[Part] => true
  case Option[Part] => true
  case _ => false
}

def getParts[T <: Product](p: T)
(using 
  mirror: Mirror.ProductOf[T],
  ev: Tuple.Filter[mirror.MirroredElemTypes, IsParts] =:= mirror.MirroredElemTypes) : List[Part] = {
    p.productIterator.toList.flatMap{e => e match {
          case p: Part => List(p)
          case ps: List[Part] => ps
          case op: Option[Part] => op.map(p => List(p)).getOrElse(List())
        }}.asInstanceOf[List[Part]]
}

它按预期工作

val p1 = Part1()

val p2 = Part2()

val p3 = Part3(p1, p2)

val p4 = Part4(p1, None, List(p3))

val p5 = Part5("part 5", p4)

@main def hello: Unit = 
  println(s"Part1 : ${getParts(p1)}") // Part1 : List()
  println(s"Part2 : ${getParts(p2)}") // Part2 : List()
  println(s"Part3 : ${getParts(p3)}") // Part3 : List(Part1(), Part2())
  println(s"Part4 : ${getParts(p4)}") // Part4 : List(Part1(), Part3(Part1(),Part2()))
  // getParts(p5) // does not compile as expected.

如何将零件列表转换为分组零件?(忽略从部件列表到分组部件的函数是部分的事实。)

Codewise 我要求实现类似的东西:

def toGroupedPart[T <: Part](parts: List[Part])
  (using 
    mirror: Mirror.ProductOf[T],
    ev: Tuple.Filter[mirror.MirroredElemTypes, IsParts] =:= mirror.MirroredElemTypes): T = ???

我会像这样使用它;

toGroupedPart[Part4](myPartList) // returns Part4
// toGroupedPart[Part5](myPartList) // does not compile because Part5 is not a grouped part.

Scastie为工作部分。

4

0 回答 0