Nic*_*man 5 scala pattern-matching existential-type scalac scala-compiler
我正在研究 Scala 中的存在类型2.12.x。为此,我正在测试以下代码:
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))
Run Code Online (Sandbox Code Playgroud)
由于类型擦除,我不希望这在运行时起作用,但是这甚至无法编译。我收到以下错误:
[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] ^
Run Code Online (Sandbox Code Playgroud)
有人可以解释这些错误吗?
(不是完整的答案,而是一些注释和链接;也许它可以作为其他人的起点)
\n在 2.12.13 中,如果出现在协变位置,编译器似乎能够证明F[_ <: X]和F[X]是相同的类型:X
println(implicitly[Option[_ <: ChildA] =:= Option[ChildA]])\nRun Code Online (Sandbox Code Playgroud)\n编译(有警告,但它编译):
\ntrait Parent\nclass ChildA extends Parent\nclass ChildB extends Parent\n\ndef whatIsInside(opt: Option[_ <: Parent]): String = {\n opt match {\n case _: Option[ChildA] => "ChildA"\n case _: Option[ChildB] => "ChildB"\n case None => "None"\n case _ => throw new Error("meh")\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n这不会编译:
\ntrait Parent\nclass ChildA extends Parent\nclass ChildB extends Parent\n\ndef whatIsInside(opt: Option[_ <: Parent]): String = {\n opt match {\n case _: Option[_ <: ChildA] => "ChildA"\n case _: Option[_ <: ChildB] => "ChildB"\n case None => "None"\n case _ => throw new Error("meh")\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n_$2所以,看起来它一定与合成类型变量的边界推断有关。
另外,这编译:
\ndef testConforms[A >: Nothing <: ChildA](ca: Option[A]): Option[_ <: Parent] = ca\nRun Code Online (Sandbox Code Playgroud)\n所以,除非我误解了规范:
\n\n\n如果存在
\n\xcf\x83对类型变量的替换a_i,\xe2\x80\xa6,a_n,使得\xcf\x83T符合,则可以确定对类型变量的pt最弱子类型约束,从而意味着符合 [预期类型] 。C1a1,\xe2\x80\xa6,anC0 \xe2\x88\xa7 C1Tpt
, thept将是Option[_ <: Parent], thena1,...,an将是单个合成类型_$2,并且约束_$2 >: Nothing <: ChildA应使该类型Option[_$2]符合Option[_ <: Parent]. 所以,看起来它应该有效,但事实并非如此。
奖金
\n如果您只是想让它工作,那么只需跳过所有这些通配符,它们是不需要的:
\ntrait Parent\nclass ChildA extends Parent\nclass ChildB extends Parent\n\ndef whatIsInside(opt: Option[Parent]): String = {\n opt match {\n case Some(_: ChildA) => "ChildA"\n case Some(_: ChildB) => "ChildB"\n case None => "None"\n case _ => throw new Error("meh")\n }\n}\n\n\nwhatIsInside(Some(new ChildA))\nwhatIsInside(Some(new ChildB))\nwhatIsInside(None)\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
368 次 |
| 最近记录: |