类型别名函数类型的隐式转换类在Scala中无法编译
在
scala中,以下代码正确编译:
class a {} class b {} object Main { implicit class Conv[f,t](val v: f ? t) extends AnyVal { def conv = v } def main(args: Array[String]) { val m = (a: a) ? new b m.conv } } 但由于某些原因,以下无法编译: class a {} class b {} object Main { type V[f,t] = f ? t implicit class Conv[f,t](val v: V[f,t]) extends AnyVal { def conv = v } def main(args: Array[String]) { val m = (a: a) ? new b m.conv } } 并附上以下讯息: value conv is not a member of a => b m.conv 为什么会发生这种情况? 编辑:是的,甚至还有一个错误 val m: V[a,b] = new V[a,b] { def apply(a: a) = new b } 解决方法
在你的第一个例子中,val v:f => t被推断为类型签名[-A,B],因为它是一个参数的函数的缩写. Function1具有类型签名,Function1 [-A,B].因此,A参数中的Contravariant类型和B参数中的协变量.
那么lambda函数,(a:a)=>新的b后面的代码,它的类型推断为一个函数从a到b.因此,类型签名是相同的和隐含的解析工作. 在第二个例子中,V [f,t] = f => t和从其创建的参数:val v:V [f,t],其类型明确指定为V [f,t].函数f => t仍然是[-A,但您明确地将类型限制为类型签名中的不变量,因此类型V在两个类型参数中都是不变的. 之后,当你声明:val m =(a:a)=>新的b类型签名仍然是第一个例子中的[-A,B].隐式分辨率无法工作,因为val在其第一个类型参数中为Contravariant,但类型V在其第一个类型参数中为Invariant. 将V的类型签名更改为V [-f,t]或V [-f,t]可以解决这个问题,隐式解析再次工作. 这提出了一个问题,为什么第二类型参数的协方差不是隐含分辨率的问题,而第一类参数的Contravariance是.我玩了一下,做了一些研究.我遇到了一些有趣的链接,这表明在隐含的解决方案中,绝对有一些限制/问题. > A Scala Ticket related to Contravariance and implicit resolution. 我必须推迟到有关Scala编译器内部知识的人员和更多细节的解析机制,但是似乎在Contravanceance的背景下,这是隐含的解决方案的一些局限性. 对于第三个例子,我想你的意思是: class a {} class b {} object Main { type V[f,t] = f => t implicit class Conv[f,t]) extends AnyVal { def conv = v } def main(args: Array[String]) { val m: V[a,b] { def apply(a: a) = new b } m.conv // does not compile } } 这是一个有趣的,我认为这是一个有点不同的原因.类型别名限制在可以改变的方面,但是使方差更严格是允许的.我不能肯定地说这里发生了什么,但这里是interesting Stack Overflow question related to type aliases and variance. 鉴于隐式解析的复杂性,结合类型声明方差与隐含的Function1方差的附加因素,我怀疑编译器根本无法解析该特定场景中的任何内容. 更改为: implicit class Conv(val v: V[_,_]) extends AnyVal { def conv = v } 意味着它在所有情况下都有效,因为您基本上对编译器说,对于Conv隐式类的目的,您不关心V类型参数的方差. 例如:以下也可以 class a {} class b {} object Main { type V[f,t] = f ? t implicit class Conv(val v: V[_,_]) extends AnyVal { def conv = v } def main(args: Array[String]) { val m = (a: a) ? new b m.conv } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |