RHS上的模式绑定器变量类型与LHS上的匹配模式不对应

为什么有部分功能

val warpedEngineers: PartialFunction[Warped[Crewmember],Warped[Engineer]] = {
  case v@Warped(Engineer(name: String)) => v.asInstanceOf[Warped[Engineer]]
}

似乎要求在RHS上投放asInstanceOf,而以下内容则不需要

val engineers: PartialFunction[Crewmember,Engineer] = {
  case v@Engineer(name) => v
}

given

sealed trait Crewmember
case class Engineer(name: String) extends Crewmember
case class Commander(name: String) extends Crewmember

case class Warped[+A <: Crewmember](v: A)

val engineers: PartialFunction[Crewmember,Engineer] = {
  case v@Engineer(name) => v
}

val warpedEngineers: PartialFunction[Warped[Crewmember],Warped[Engineer]] = {
  case v@Warped(Engineer(name: String)) => v.asInstanceOf[Warped[Engineer]]
}

val crew: List[Crewmember] = 
  List(Engineer("Geordi"),Commander("Picard"),Engineer("Scott"),Commander("Kirk"))

val warpedCrew: List[Warped[Crewmember]] = 
  List(Warped(Engineer("Geordi")),Warped(Commander("Picard")),Warped(Engineer("Scott")),Warped(Commander("Kirk")))

crew collect engineers
// res0: List[Engineer] = List(Engineer(Geordi),Engineer(Scott))

warpedCrew collect warpedEngineers
// res1: List[Warped[Engineer]] = List(Warped(Engineer(Geordi)),Warped(Engineer(Scott)))

像这样可以避免使用asInstanceOf进行铸造

case Warped(eng: Engineer) => Warped(eng) 

但是我想知道为什么编译器不插入隐式asInstanceOf而是将v键入Warped[Crewmember]

val warpedEngineers: PartialFunction[Warped[Crewmember],Warped[Engineer]] = {
  case v@Warped(Engineer(name: String)) => v 
}

Error: type mismatch;
 found   : Warped[Crewmember]
 required: Warped[Engineer]
      case v@Warped(Engineer(name: String)) => v

根据SLS 8.1.3: Pattern Binders

模式绑定器?@?由模式变量?和模式组成 ?。变量type的类型是由隐含的静态类型?。 模式?。该模式与该模式匹配的任何值?匹配 ?,它将变量名绑定到该值。

如果模式matches仅匹配的值,则模式?表示类型?。 ?类型。

cycannon 回答:RHS上的模式绑定器变量类型与LHS上的匹配模式不对应

Warped(Engineer(name))在左侧

case v@Warped(Engineer(name: String)) => v

具有静态类型Warped[Crewmember],因为这就是您在类型签名中写的内容

val warpedEngineers: PartialFunction[Warped[Crewmember],...

因此,如果您仅在右侧写v,则类型不匹配。

Warped(Engineer(name))的右侧和左侧

case Warped(Engineer(name)) => Warped(Engineer(name))

看起来很相似,但是有所不同,因为它们的类型不同。它们实际上是Warped[Crewmember](Engineer(name))Warped[Engineer](Engineer(name))。由于协方差,Warped[Engineer]Warped[Crewmember],反之亦然。

编译器应该如何猜测应该在此处插入asInstanceOf而不应该在val x: Int = "a"中插入?

如果您更改签名

val warpedEngineers: PartialFunction[Warped[Engineer],Warped[Engineer]] = {
  case v@Warped(Engineer(name)) => v
}

然后v的静态类型将是Warped[Engineer],并且代码将被编译。

类似地,如果您使用键入模式

val warpedEngineers: PartialFunction[Warped[Crewmember],Warped[Engineer]] = {
  case v: Warped[Engineer] => v
}

然后v的静态类型将是Warped[Engineer],并且代码将被编译。

似乎是

中的规范模式v@Warped(Engineer(name))
val warpedEngineers: PartialFunction[Warped[Crewmember],Warped[Engineer]] = {
  case v@Warped(Engineer(name)) => ...
}

“暗示”类型Warped[Crewmember](由于签名)。

本文链接:https://www.f2er.com/2338071.html

大家都在问