[英]Scala compilation error: not found: type _$1
I am researching about existential types in Scala 2.12.x
.我正在研究 Scala 2.12.x
中的存在类型。 For that I'm testing the following code:为此,我正在测试以下代码:
trait Parent
class ChildA extends Parent
class ChildB extends Parent
def whatIsInside(opt: Option[_ <: Parent]): String = {
opt match {
case _: Option[_ <: ChildA] => "ChildA"
case _: Option[_ <: ChildB] => "ChildB"
case _ => throw new IllegalArgumentException("unknown type")
}
}
whatIsInside(Some(new ChildA))
I don't expect this to work at runtime because of type erasure, but nevertheless this does not even compile.由于类型擦除,我不希望它在运行时工作,但是这甚至不能编译。 I am getting the following error:我收到以下错误:
[error] ExistentialTypes.scala:12:24: not found: type _$2
[error] case _: Option[_ <: ChildA] => "ChildA"
[error] ^
[error] ExistentialTypes.scala:13:24: not found: type _$3
[error] case _: Option[_ <: ChildB] => "ChildB"
[error] ^
Can someone explain these errors?有人可以解释这些错误吗?
(Not a full answer, but a few notes and links; Maybe it can serve as a starting point for someone else) (不是完整的答案,而是一些注释和链接;也许它可以作为其他人的起点)
In 2.12.13, the compiler seems to be able to prove that F[_ <: X]
and F[X]
are the same type if X
occurs in covariant position:在 2.12.13 中,如果X
出现在协变 position 中,编译器似乎能够证明F[_ <: X]
和F[X]
是同一类型:
println(implicitly[Option[_ <: ChildA] =:= Option[ChildA]])
This compiles (with warnings, but it compiles):这编译(带有警告,但它编译):
trait Parent
class ChildA extends Parent
class ChildB extends Parent
def whatIsInside(opt: Option[_ <: Parent]): String = {
opt match {
case _: Option[ChildA] => "ChildA"
case _: Option[ChildB] => "ChildB"
case None => "None"
case _ => throw new Error("meh")
}
}
This does not compile:这不会编译:
trait Parent
class ChildA extends Parent
class ChildB extends Parent
def whatIsInside(opt: Option[_ <: Parent]): String = {
opt match {
case _: Option[_ <: ChildA] => "ChildA"
case _: Option[_ <: ChildB] => "ChildB"
case None => "None"
case _ => throw new Error("meh")
}
}
So, it seems that it must have something to do with the bounds inference for the synthetic _$2
type-variable.因此,它似乎必须与合成_$2
类型变量的边界推断有关。
Also, this compiles:此外,这编译:
def testConforms[A >: Nothing <: ChildA](ca: Option[A]): Option[_ <: Parent] = ca
so, unless I'm misinterpreting the spec :所以,除非我误解了规范:
If there exists a substitution
σ
over the type variablesa_i,…,a_n
such thatσT
conforms topt
, one determines the weakest subtype constraintsC1
over the type variablesa1,…,an
such thatC0 ∧ C1
implies thatT
conforms to [the expected type]pt
.如果在类型变量a_i,…,a_n
上存在替换σ
,使得σT
符合pt
,则确定类型变量a1,…,an
上的最弱子类型约束C1
,使得C0 ∧ C1
意味着T
符合 [the预期类型]pt
。
, the pt
would be Option[_ <: Parent]
, then a1,...,an
would be the single synthetic type _$2
, and the constraints _$2 >: Nothing <: ChildA
should make the type Option[_$2]
conform to Option[_ <: Parent]
. , pt
将是Option[_ <: Parent]
,然后a1,...,an
将是单个合成类型_$2
,并且约束_$2 >: Nothing <: ChildA
应该使类型Option[_$2]
符合Option[_ <: Parent]
。 So, it seems that it should work, but doesn't.所以,它似乎应该工作,但没有。
Bonus奖金
If you just wanted to make it work, then just skip all those wildcards, they aren't needed:如果您只是想让它工作,那么只需跳过所有这些通配符,它们不是必需的:
trait Parent
class ChildA extends Parent
class ChildB extends Parent
def whatIsInside(opt: Option[Parent]): String = {
opt match {
case Some(_: ChildA) => "ChildA"
case Some(_: ChildB) => "ChildB"
case None => "None"
case _ => throw new Error("meh")
}
}
whatIsInside(Some(new ChildA))
whatIsInside(Some(new ChildB))
whatIsInside(None)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.