【问题标题】:Scala 3 - tuple from nested case classScala 3 - 来自嵌套案例类的元组
【发布时间】:2021-11-06 19:25:24
【问题描述】:

使用 scala 3,您可以使用 Tuple.fromProductTyped 从案例类中获取元组。

我想获取嵌套案例类的所有字段,例如:

    case class Baz(x: String)
    case class Employee(name: Baz, number: Int, manager: Boolean)

    Tuple.fromProductTyped(Employee(Baz("hello"), 42, false))  // (Baz(hello),42,false) but I need (hello,42,false)

下面的代码尝试获取嵌套案例类的元组,但在第 *** 行失败

no implicit argument of type deriving.Mirror.ProductOf[Product] was found for parameter m of method fromProductTyped in object Tuple
              val tuple2 = Tuple.fromProductTyped(x)
    trait RowEncoder[A] {
      def encodeRow(a: A): List[String]
    }

    def tupleToCsv[A <: Tuple: RowEncoder](tuple: A): List[String] = summon[RowEncoder[A]].encodeRow(tuple)

    case class Baz(x: String)
    case class Employee(name: Baz, number: Int, manager: Boolean)


    def flatTuple[A <: Tuple](tuple: A): Tuple = {
      tuple match {
        case x *: xs =>
          x match {
            case x: Product =>
              val tuple2 = Tuple.fromProductTyped(x) // *** 
              flatTuple(tuple2) ++ flatTuple(xs)
            case x => x *: flatTuple(xs)
          }
        case _ => EmptyTuple
      }
    }

    val tuple = Tuple.fromProductTyped(Employee(Baz("hello"), 42, false))
    println(flatTuple(tuple)) // expected: (hello,42,false)

要测试在第 *** 行将 x 替换为 Baz("hello")

我该如何解决?

【问题讨论】:

    标签: scala scala-3


    【解决方案1】:

    你必须使用Tuple.fromProduct(x) 而不是 Tuple.fromProductTyped(x):

     def flatTuple[A <: Tuple](tuple: A): Tuple = {
      tuple match {
       case x *: xs =>
        x match {
         case x: Product =>
          val tuple2 = Tuple.fromProduct(x) // ***
          flatTuple(tuple2) ++ flatTuple(xs)
         case x => x *: flatTuple(xs)
        }
       case _ => EmptyTuple
      }
     }
    

    【讨论】:

      【解决方案2】:

      如果您关心返回元组的确切类型,则以下内容就足够了:

      scala> def flat(any: Any): Tuple = any match
           |   case p: Product => p.productIterator.map(flat).foldLeft(EmptyTuple: Tuple)(_ ++ _)
           |   case a => Tuple1(a)
           |
      def flat(any: Any): Tuple
      
      scala> val flatTuple = flat(Employee(Baz("hello"), 42, false))
      val flatTuple: Tuple = (hello,42,false)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-10
        • 1970-01-01
        • 1970-01-01
        • 2019-11-08
        • 1970-01-01
        相关资源
        最近更新 更多