加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

类型别名函数类型的隐式转换类在Scala中无法编译

发布时间:2020-12-16 21:30:49 所属栏目:安全 来源:网络整理
导读:在 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 {
在 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.
> A long discussion on google groups related to the ticket
> Some workaround code for Contravariance and implicit resolutions in some scenarios.

我必须推迟到有关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
  }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读