【发布时间】:2017-12-19 10:39:02
【问题描述】:
使用 Scala...我不知道如何以混合类型绑定和协变的方式使用多态性。
简而言之,我认为我需要类似这种类型签名的东西...但是如果您按照我的虚拟示例进行操作,您就会明白我为什么会出现在这里...也许我错了。
def func[+T <: U](func: Seq[T] => T)(iter: Iterator[String]): Map[String, String] = ???
但是这种方法会产生...
>> error: ']' expected but identifier found
这是一个虚拟示例,演示了我正在尝试做的事情...我可以通过仅使用基本特征 Record 来回避这个问题...但我想让它与多态性一起工作实际代码中的其他原因。
设置
// underlying trait to hold key and value
trait Record {
def k: String
def v: String
def isDefined: Boolean
}
// companion object with apply method
object Record {
def apply(s: String): Record = s.split(",") match {
case Array(k,v) => new ValidRecord(k,v).asInstanceOf[Record]
case _ => EmptyRecord.asInstanceOf[Record]
}
}
// singleton for empty records
object EmptyRecord extends Record {
val k = ""
val v = ""
val isDefined = false
}
// class for actual data
class ValidRecord(val k: String, val v: String) extends Record {
val isDefined = true
}
多态函数
注意 - 从 Iterator 到 Seq 这里看起来有问题...我正在从 src/main/resources 中读取一个文件...它以 Iterator 的形式出现...我最终需要将它放入映射,所以 .toSeq 和 .groupBy 似乎是合乎逻辑的步骤......它可能只有 100MB 和一百万左右的记录,所以这很好用......但如果有更聪明的方式来从头到尾,我很开放对那个批评也是如此。
def iter_2_map[T <: Record](func: Seq[T] => T)(iter: Iterator[String]): Map[String, String] = {
iter // iterator of raw data
.map(Record.apply) // Iterator[Record]
.toSeq // gives .groupBy() method
.groupBy(_.k) // Map[k -> Seq[Record]]; one Seq of records per k
.mapValues(func) // <<< ERROR HERE //function to reduce Seq[Record] to 1 Record
.filter(_._2.isDefined) // get rid of empty results
.mapValues(_.v) // target of Map is just v
}
错误
found : Seq[T] => T
required: Seq[Record] => ?
.mapValues(func)
^
如果我分解所有这些步骤并在每个相关步骤中声明类型...错误将变为此...
found : Seq[T] => T
required: Seq[Record] => Record
.mapValues(func)
^
所以这就是我被难住的地方。我认为使 T 协变解决了这个问题... T 是 Record 的声明子类型,但也许它没有将 Seq[T] 识别为 <: seq>
但是进行此更改会在顶部产生错误...
def iter_2_map[+T <% Record](func: Seq[T] => T)(iter: Iterator[String]): Map[String, String] = {
???
}
回到这个...
>> error: ']' expected but identifier found
我是否走在正确的轨道上?
【问题讨论】:
-
不清楚你的
trait Record是否应该是sealed。换句话说,EmptyRecord和ValidRecord是唯一预期的子类吗?或者您想创建具有更多字段和其他解析逻辑的更具体的类型?所以当你写T <: Record时,不清楚你在想什么T。一方面,您显式调用Record.apply,因此除了这两个之外您无法获得任何其他内容。另一方面,如果您使用Record.apply,您可以同时获得它们,因此您不能将类型缩小到比只是Record。总结一下:告诉我们你将如何使用你的iter_2_map
标签: scala polymorphism covariance type-bounds