为啥方差注释会导致 Scala 无法推断出这种子类型关系?
Posted
技术标签:
【中文标题】为啥方差注释会导致 Scala 无法推断出这种子类型关系?【英文标题】:Why does a variance annotation cause this subtyping relation not to be inferred by Scala?为什么方差注释会导致 Scala 无法推断出这种子类型关系? 【发布时间】:2014-06-20 23:37:45 【问题描述】:在代码中
sealed trait Node[+T]
case class I[C]() extends Node[C => C]
def test[A, B](n: Node[A => B]) = n match
case i: I[c] =>
val cId: c => c = identity _
val ab: A => B = cId
Scala 给出c => c
不是A => B
的错误。去掉Node[+T]
中的variance注解即可解决错误。
我很困惑,因为我相信,在存在差异注释的情况下,匹配 i: I[c]
应该创建规则 (c => c) <:< (A => B)
,这就是编译该行所需的全部内容。我错过了什么?
【问题讨论】:
函数参数的自变量是 CONTRAvariant。这不是答案,而是猜测。 @MikeG。嗯,我想知道这是否可能涉及,但我看不出是怎么回事——=>
的差异似乎在这里没有发挥作用。当然,如果我是对的,我应该能够在没有函数类型的情况下重现这个示例,但它仍然会失败。也许我会试试看。
经过进一步的实验,这似乎与 =>
... 的变化无关,甚至与 =>
的差异无关,但似乎与 @ 中的重复类型变量有关987654331@。仍然不确定为什么这很重要。
那很好。我不知道这是否是一个 patmat 错误。我像cmets一样通过动作。 issues.scala-lang.org/browse/SI-8563
我认为问题出在类型差异上。特别是当i: I[C]
匹配时,c =:= A
应该为真。 (因此所有以下语句都应该编译)
【参考方案1】:
免责声明:c
在运行时被删除,您的匹配将无法正常工作。您正在匹配 I[_]
如果您的 Node
是不变的,Node[A]
是 Node[B]
的子类,仅当且仅当 A=B
。这迫使
n
传递给test[A, B](n: Node[A => B])
成为真正的Node[A => B]
如果你推理失败,如果你的 n
与模式 I[Something]
匹配任何 Something
,A 和 B 必须是 Something
类型
如果 Node 是协变的,由于 Function1[-A,+B]
的定义,您可以调用
test[A,B](n)
其中n
是Node[A1 =>B1]
其中A1>:A
和B1<:B
(等式1)
因此,如果您的 n
与 I[C]
匹配,则意味着 A1 = C
和 B1 = C
如果你替换等式1中的C
,你会得到C >: A
和C<:B
(等式2)
因此下面的赋值不再有效
f: A => B = C => C
为了使左侧可以从右侧分配,我们需要 C => C
为 Function1[-A,+B]
这意味着 A >: C
和 B <: C
但从等式 2 我们知道这不成立(除了 C = A 和 C = B 的情况,并且没有证据表明情况如此,除非您的节点是不变的)
【讨论】:
以上是关于为啥方差注释会导致 Scala 无法推断出这种子类型关系?的主要内容,如果未能解决你的问题,请参考以下文章