Scala Generics - ADT 中的通用提取器方法
Scala Generics - generic extractor method in an ADT
我有一个类似的 ADT;
sealed trait Dimension
case object Customer extends Dimension
case object Brand extends Dimension
case object Product extends Dimension
现在这个 ADT 表示数据中的值 class
case class Record(custId: Long, prodId: Int, brand: String)
我如何编写一个 'dimension extractor' 以便如果我传入任何 Dimension
类型和一个 Record
的实例我得到它代表的值?
也就是说我有一个Seq[Dimension](Brand,Customer).foreach{d => println(d.extract(aRecord))}
首先想到的是做类似的事情;
trait DimExtractor[A,B] {
val extract = A => B
}
然后更改ADT:
case object Brand extends Dimension with DimExtractor[Record, String] {
val extract = (r: Record) => r.brand
}
有没有办法根据r.brand的return类型隐式获取String类型?也许让这个成为一个def?
但这行不通,因为 Seq[Dimension with DimExtractor]
无法编译,因为它需要类型参数...但我有很多 DimExtractor[Record, ?]
(即一个用于品牌的 return 是字符串,对于 return 很长的客户等等...
我可以将其设为 DimExtractor[Record, Any]... 但这又似乎不对。
有什么更好的方法来做到这一点?
你有 3 个 Dimension
特征的子类(对象),提取器的 return 值取决于参数类型(考虑 a
和 b
作为参数a.method(b)
中的 method
)。您可以使用依赖于路径的类型。
sealed trait Dimension {
}
trait DimExtractor[R] {
type Ret
def extract(r: R): Ret
}
case object Customer extends Dimension with DimExtractor[Record] {
type Ret = Long
def extract(r: Record): Ret = r.custId
}
case object Brand extends Dimension with DimExtractor[Record] {
type Ret = String
def extract(r: Record): Ret = r.brand
}
case object Product extends Dimension with DimExtractor[Record] {
type Ret = Int
def extract(r: Record): Ret = r.prodId
}
case class Record(custId: Long, prodId: Int, brand: String)
现在你可以把你的例子写成
val aRecord = Record(1, 1, "asd")
Seq[DimExtractor[Record]](Brand, Customer).foreach { d => println(d.extract(aRecord)) }
我有一个类似的 ADT;
sealed trait Dimension
case object Customer extends Dimension
case object Brand extends Dimension
case object Product extends Dimension
现在这个 ADT 表示数据中的值 class
case class Record(custId: Long, prodId: Int, brand: String)
我如何编写一个 'dimension extractor' 以便如果我传入任何 Dimension
类型和一个 Record
的实例我得到它代表的值?
也就是说我有一个Seq[Dimension](Brand,Customer).foreach{d => println(d.extract(aRecord))}
首先想到的是做类似的事情;
trait DimExtractor[A,B] {
val extract = A => B
}
然后更改ADT:
case object Brand extends Dimension with DimExtractor[Record, String] {
val extract = (r: Record) => r.brand
}
有没有办法根据r.brand的return类型隐式获取String类型?也许让这个成为一个def?
但这行不通,因为 Seq[Dimension with DimExtractor]
无法编译,因为它需要类型参数...但我有很多 DimExtractor[Record, ?]
(即一个用于品牌的 return 是字符串,对于 return 很长的客户等等...
我可以将其设为 DimExtractor[Record, Any]... 但这又似乎不对。
有什么更好的方法来做到这一点?
你有 3 个 Dimension
特征的子类(对象),提取器的 return 值取决于参数类型(考虑 a
和 b
作为参数a.method(b)
中的 method
)。您可以使用依赖于路径的类型。
sealed trait Dimension {
}
trait DimExtractor[R] {
type Ret
def extract(r: R): Ret
}
case object Customer extends Dimension with DimExtractor[Record] {
type Ret = Long
def extract(r: Record): Ret = r.custId
}
case object Brand extends Dimension with DimExtractor[Record] {
type Ret = String
def extract(r: Record): Ret = r.brand
}
case object Product extends Dimension with DimExtractor[Record] {
type Ret = Int
def extract(r: Record): Ret = r.prodId
}
case class Record(custId: Long, prodId: Int, brand: String)
现在你可以把你的例子写成
val aRecord = Record(1, 1, "asd")
Seq[DimExtractor[Record]](Brand, Customer).foreach { d => println(d.extract(aRecord)) }