With scala 3 you can get a tuple from a case class using Tuple.fromProductTyped
.
I'd like get all fields of nested case classes, example:
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)
The code below tries to get the tuple of nested case classes but fails on row ***
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)
To test replace x
with Baz("hello")
at row ***
how can I fix it?
CodePudding user response:
You have to use Tuple.fromProduct(x)
instead of 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
}
}
CodePudding user response:
If you do not care the exact type of the return tuple, the following is enough:
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)