假设Lofty是一个封闭的特性,而Earthy是它的案例类之一。在这样的匹配中:
loftyItem match {
...
case e @ Earthy(x,y,z) => { foo(e) }
...
}如果foo期望一个Earthy作为参数,编译器就会崩溃,因为e只被推断为Lofty类型。我可以解决这个问题,但它不符合我的模式,事情应该是怎样的。(我正在使用Scala2.13.5。)有人能解释为什么编译器的行为是有意义的,并让我再次对Scala感到高兴吗?
在答复意见时,让我更确切地说:
object QTest {
trait Ethereal
case class Lofty[A <: Ethereal](val slotMaybe: Option[A]) {
}
class Earthy(val field: Int) extends Ethereal
object Earthy {
def apply(fx: Int): Earthy = {
new Earthy(fx)
}
def unapply(x: Ethereal): Option[Int] = x match {
case y: Earthy => Some(y.field)
case _ => None
}
}
def testReally(just: Lofty[Ethereal]):
Lofty[Earthy] = {
just.slotMaybe match {
case Some(c) => c match {
case cnfC @ Earthy(i) => {
just.copy(slotMaybe = Some(cnfC))
}
case _ => throw new RuntimeException("oops")
}
case _ => throw new RuntimeException("oops")
}
}
}编译这会产生错误:
QTest.scala:25: error: type mismatch;
found : QTest.Ethereal
required: QTest.Earthy
just.copy(slotMaybe = Some(cnfC))我显然得出了一个结论,但完整的例子似乎也有同样的问题。为什么编译器要推断Ethereal类型为cnfC而不是Earthy?即使编译器在大多数@的使用中都得到了正确的类型,为什么它会在这里出错呢?
发布于 2021-06-06 19:49:08
如果模式只匹配类型
p的值,那么模式T就意味着该类型的T。
模式Earthy(i)在
case cnfC @ Earthy(i) =>表示萃取器模式,意味着它将根据您对unapply的定义进行匹配。
object Earthy {
def unapply(x: Ethereal): Option[Int] = ???
}因为声明的x类型是更宽的Ethereal,而不是更窄的Earthy,所以它将不匹配。
..。只有
T类型的值
但是它也可以与T = Earthy的其他子类型相匹配。因此,编译器只能确定它将是一些Ethereal。
如果希望将其编译为提取器模式,则将unapply声明为
object Earthy {
def unapply(x: Earthy): Option[Int] = ???
}或者更好的是用例类来代替它自动获得正确的unapply
case class Earthy(field: Int) extends Etherealhttps://stackoverflow.com/questions/67862964
复制相似问题