如何执行通用元组->;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类在其伴生对象中都有一个
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)
}
}