Home > Enterprise >  Scala 3 - Instantiate class from List[String]
Scala 3 - Instantiate class from List[String]

Time:09-17

in Scala 3, I'm trying to instantiate a case class from a list of String, example

the list List("bob", "2.2", "1") fit the fields of Foo:

case class Foo(aString: String, aDouble: Double, aInt: Int)

and listStringTOclass[Foo](List("bob", "2.2", "1")) returns Foo(bob,2.2,1)

But I can't retrive the types of Foo elements, in my code I wrote val types = List("String", "Double", "Int") but I should use MirroredElemTypes to generalize, any help?

    import scala.deriving.Mirror
    import scala.compiletime.summonAll

    def listStringTOclass[A](stringValues:List[String])(using m: Mirror.ProductOf[A]) = {
      type TheType = String
      type StringValue = String

      val types = List("String","Double","Int") // m.MirroredElemTypes, should be Type not string

      def valueList(ll: List[(TheType, StringValue)]): List[Any] = ll match {
        case Nil => Nil
        case h::t if h._2 == "String" => h._1 :: valueList(t)
        case h::t if h._2 == "Int"    => h._1.toInt :: valueList(t)
        case h::t if h._2 == "Double" => h._1.toDouble :: valueList(t)
        case _ => ???
      }

      val tv: List[(TheType, StringValue)] = stringValues.zip(types)
      val l: List[Any] = valueList(tv)
      println(l) // List(bob, 2.2, 1)
      val tuple: Tuple = l.foldRight[Tuple](EmptyTuple)(_ *: _)
      println(tuple) //  (bob,2.2,1)

      m.fromProduct(tuple)
    }


    case class Foo(aString: String, aDouble: Double, aInt: Int)

    val o = listStringTOclass[Foo](List("bob", "2.2", "1"))
    println(o) // Foo(bob,2.2,1)

CodePudding user response:

How about this (works in scala 3.0.1):

scala> object list2class {
     |   import scala.deriving.Mirror
     |
     |   trait Decoder[A, B] extends (A => B)
     |   object Decoder:
     |     given Decoder[String, String] = s => s
     |     given Decoder[String, Int] = _.toInt
     |     given Decoder[String, Double] = _.toDouble
     |     given Decoder[List[String], EmptyTuple] = {
     |       case Nil => EmptyTuple
     |       case s => throw IllegalArgumentException(s.toString())
     |     }
     |     given [H, T <: Tuple](using dh: Decoder[String, H], dt: Decoder[List[String], T]): Decoder[List[String], H *: T] = {
     |       case h::t => dh(h) *: dt(t)
     |       case Nil => throw IndexOutOfBoundsException()
     |     }
     |
     |   def apply[A](xs: List[String])(using m: Mirror.ProductOf[A], d: Decoder[List[String], m.MirroredElemTypes]): A =
     |     m.fromProduct(d(xs))
     | }
// defined object list2class

scala> case class Foo(aString: String, aDouble: Double, aInt: Int)
// defined case class Foo

scala> list2class[Foo](List("bob", "2.2", "1"))
val res0: Foo = Foo(bob,2.2,1)

CodePudding user response:

Consider using shapeless for semi-automatic case class derivation via HList "heterogeneous list".

  • Related