什么是从数据容器(例如case class)中提取类型的最佳方法?
例如,如果我有一个标记类型
然后根据需要添加它们。
例如,如果我有一个标记类型
trait PID
,它是一个带有标记Int的type ProductId = Int with Tagged[PID]
或者Scalaz风格的type ProductId = Int @@ PID
,以及产品中的其他字段type Name = String @@ PName
等等,并且一个数据容器包含了产品的属性;case class Product(pid: ProductId, name: Name, weight: Weight)
如何在不使用反射的情况下编写通用提取器 A => B
的方法?这个问题是因为我想在运行时从产品容器中动态提取一个字段。也就是说,用户传递了他们想要提取的产品属性。
比如,如果我想动态获取ProductId
,我能否编写一个方法,该方法接受类型并返回值,例如:
trait Extractor[A] {
def extract[B](i: A): B = //get type B from the Product class
}
或许我在过度复杂化问题。
我可以编写一个简单的提取器类,它接受A => B函数并为每种类型定义它;
trait Getter[A, B] {
def extract(i: A): B
}
//... mix this in...
trait GetPID extends Getter[Product, ProductId] {
override def extract(implicit i: Product) = i.pid
}
trait GetName extends Getter[Product, Name] {
override def extract(implicit i: Product) = i.name
}
然后根据需要添加它们。
val dyn = new DynamicProductExtractor with GetPID
dyn.extract
但这似乎很麻烦。
我认为像 Lens 这样的工具在这里会很有用。
scala> case class Product(pid: ProductId, name: Name, weight: Weight) error: type mismatch; found : Double required: AnyRef Note: an implicit exists from scala.Double => java.lang.Double, but methods inherited from Object are rendered ambiguous. This is to avoid a blanket implicit which would convert any scala.Double to any AnyRef. You may wish to use a type ascription:
x: java.lang.Double.
@TravisBrown,有什么想法吗? - NightWolfA
和C
类型参数,并要求相同的Generic.Aux
和Selector
证据来使我的解决方案通用化。 - Travis Brown