繁体   English   中英

映射成员使用存在类型键入的类的scala类型错误

[英]scala type error for class with map member typed with existential type

我在Scala中遇到无法理解的类型系统问题。 下面的代码段说明了该问题。 能够在具有键类型为A或A的子类型的类中拥有映射成员的正确方法是什么? 我认为第二种方法是正确的,但是当我尝试从地图中获取元素时出现错误。 这与存在类型有关吗?

sealed abstract class MyBaseType
case class Concrete1() extends MyBaseType
case class Concrete2() extends MyBaseType

case class DictVariant1(data: Map[MyBaseType, Double])
case class DictVariant2(data: Map[_ <: MyBaseType, Double])

object App {
  def main(args: Array[String]) {
    val d = List((Concrete1(), 3.5)).toMap

    /* this fails with:
     * type mismatch;  
     * found: scala.collection.immutable.Map[Concrete1,Double]  
     * required: Map[MyBaseType,Double] 
     * Note: Concrete1 <: MyBaseType, but trait Map is invariant in type A. 
     * You may wish to investigate a wildcard type such as `_ <: MyBaseType`. 
     * (SLS 3.2.10)
     * 
     */
    val dv1 = DictVariant1(d)
    dv1.data.get(d)

    /* Works fine */
    val dv2 = DictVariant2(d)

    /* this fails with:
     * type mismatch;  
     * found: d.type (with underlying type scala.collection.immutable.Map[Concrete1,Double])  
     * required: _$1    
     * 
     */
    dv2.data.get(Concrete1())
  }
}

除非您明确要求将密钥作为静态正确的子类型取回(这似乎不太可能),否则以下方法将起作用:

case class DictVariant1(data: Map[MyBaseType, Double])
val d = List((Concrete1() : MyBaseType, 3.5)).toMap
val dv1 = DictVariant1(d)

使用类型描述强制将Concrete1()视为基本类型的实例; 如果向d添加显式类型,则将获得相同的效果:

val d : Map[MyBaseType, Double] = ....

或者,如果您放入多个条目,以便类型推断器选择基本类型:

val d = List((Concrete1(), 3.5), (Concrete2(), 4.5)).toMap

但是,您使用的“获取”总是会失败,因为您正试图将整个Map用作索引:如果您提供了合理的键,它会很好地工作:

dv1.data.get(Concrete1())

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM