如何执行通用元组->;Scala中的case类转换?

如何执行通用元组->;Scala中的case类转换?,scala,Scala,假设有人提供了一个函数: def getTupleData[T](source: String): List[T] = { // ... } 我需要编写一个函数,它以case类C作为类型参数,并在上述函数的帮助下返回List[C]。以下是我到目前为止得到的信息: def getCaseClassData[C](source: String): List[C] = { // Somehow get T from C. // For example, if C is case clas

假设有人提供了一个函数:

def getTupleData[T](source: String): List[T] = {
  // ...
}
我需要编写一个函数,它以case类
C
作为类型参数,并在上述函数的帮助下返回
List[C]
。以下是我到目前为止得到的信息:

def getCaseClassData[C](source: String): List[C] = {
  // Somehow get T from C.
  // For example, if C is case class MyCaseClass(a: Int, b: Long), then T is (Int, Long)
  // How to get T?      

  getTupleData[T](source) map { tuple: T =>
    // Somehow convert tuple into a case class instance with the case class type parameter
    // C.tupled(tuple) ??  Type parameter cannot be used like this. :(
  }
}
更具体地说,我想问两个问题:

  • 如何从表示case类的类型参数显式获取元组的类型,以便将其用作类型参数
  • 如何从元组实例创建case类实例,而不知道case类的实际名称,而只知道类型参数

  • 你找不到任何简单直接的方法。如果你准备好了更复杂的解决方案,请容忍我

    每个case类在其伴生对象中都有一个
    apply
    方法,该方法实例化该类。通过在此方法上调用
    tuple
    (在eta扩展之后),您将获得一个函数,该函数接受一个tuple并创建相应的case类实例

    当然,现在的问题是每个case类的
    apply
    都有不同的签名。我们可以通过引入一个表示case类工厂的类型类来解决这个问题,并通过一个宏提供这个类型类的实例(该宏只会委托给case类的
    apply
    方法)

    相当整洁。有了这个类型类,
    getCaseClassData
    就变成:

    def getCaseClassData[C](source: String)(implicit f: CaseClassFactory[C,_]): List[C] = {
      getTupleData[f.Tuple](source) map { tuple: f.Tuple =>
        f(tuple)
      }
    }
    

    这并没有回答我的问题:1)我在这里谈论的是泛型,与我所看到的完全不同,2)你提到的问题是从case类转换为tuple。用
    t
    type表示什么?我希望它是对应tuple的类型。
    scala> case class Person(name: String, age: Long)
    defined class Person
    
    scala> val f = CaseClassFactory[Person]
    f: CaseClassFactory[Person]{type Tuple = (String, Long)} = $anon$1@63adb42c
    
    scala> val x: f.Tuple = ("aze", 123)
    x: f.Tuple = (aze,123)
    
    scala> implicitly[f.Tuple =:= (String, Long)]
    res3: =:=[f.Tuple,(String, Long)] = <function1>
    
    scala> f(("aze", 123))
    res4: Person = Person(aze,123)
    
    scala> implicit class TupleToCaseClassOps[T](val t: T) extends AnyVal {
         |   def toCaseClass[C](implicit f: CaseClassFactory[C,T]): C = {
         |     f(t)
         |   }
         | }
    defined class TupleToCaseClassOps
    
    scala> case class Person(name: String, age: Long)
    defined class Person
    
    scala> ("john", 21).toCaseClass[Person]
    res5: Person = Person(john,21)
    
    def getCaseClassData[C](source: String)(implicit f: CaseClassFactory[C,_]): List[C] = {
      getTupleData[f.Tuple](source) map { tuple: f.Tuple =>
        f(tuple)
      }
    }