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

为什么Scala推断路径依赖类型的路径 – 甚至从显式的自引用?

发布时间:2020-12-16 09:18:35 所属栏目:安全 来源:网络整理
导读:我想将一个对象传递给一个接受一个投影类型的参数的函数,并且得到 Scala来推断对象的类型来自包围对象的对象.这里有一些简单的代码来说明难点: trait Cult { cult_ = case class CultLeader(personality: Personality) { val cult = cult_ val follower = p
我想将一个对象传递给一个接受一个投影类型的参数的函数,并且得到 Scala来推断对象的类型来自包围对象的对象.这里有一些简单的代码来说明难点:

trait Cult { cult_ =>
  case class CultLeader(personality: Personality) {
    val cult = cult_
    val follower = personality.attractFollower(this)
  }
  case class Follower(leader: CultLeader,name: String)
}

trait Personality {
  def attractFollower(leader: Cult#CultLeader) =
    leader.cult.Follower(leader,"Fred")   <-- THIS LINE FAILS TO COMPILE
}

换句话说,Cultleader的个性应该吸引与追随者相同的崇拜者.

Scala 2.11.2编译器说:

TypeProjection.scala:11: error: type mismatch;
 found   : Cult#CultLeader
 required: leader.cult.CultLeader
    leader.cult.Follower(leader,"Fred")
                         ^

如果我添加一个演员,它会编译并正确运行,如下所示:

leader.cult.Follower(leader.asInstanceOf[leader.cult.CultLeader],"Fred")

这似乎很笨拙,它引入了在编译时应该可以推出的东西的运行时检查.至少我有一个解决方法.如何让Scala编译器推断领导者的类型其实是leader.cult.CultLeader?

我不希望通过邪教作为另一个参数来吸引浪漫者.在我的实际代码中,这可能会导致很多丑恶的传播邪教参数 – 当它真的不需要通过.

解决方法

简单的方法是:

trait Cult { cult_ =>
  case class CultLeader(personality: Personality) {
    val cult = cult_
    val follower = personality.attractFollower(this)
  }
  case class Follower(leader: Cult#CultLeader,name: String) // <-- Cult#CultLeader here
}

trait Personality {
  def attractFollower(leader: Cult#CultLeader) =
    leader.cult.Follower(leader,"Fred")   
}

// Exiting paste mode,now interpreting.

defined trait Cult
defined trait Personality

在这里,您明确指定了跟随者可以采取任何投影,您实际上正在尝试强制使用asInstanceOf.

还有另一种方法:

trait Cult {
  case class CultLeader(personality: Personality) {
    def fl(name: String) = Follower(this,name)
    val follower = personality.attractFollower(this)
  }
  case class Follower(leader: CultLeader,name: String)
}

trait Personality {
  def attractFollower(leader: Cult#CultLeader) = leader.fl("Fred")
}

要么

trait Cult {
  case class CultLeader(personality: Personality) { ld =>
    val follower = personality.attractFollower(this)
    case class Follower(name: String) { val leader = ld }
  }
}

trait Personality {
  def attractFollower(leader: Cult#CultLeader) = leader.Follower("Fred")   
}

更新:这个例子可以使它更清楚为什么Scala正在做她正在做的事情:

trait Cult { cult_ =>
  case class CultLeader(personality: Personality) {
    val cult: Cult = cult_ //could be new Cult{} as well
    val l = this.asInstanceOf[cult.CultLeader] //We have to do asInstanceOf here because Scala have no glue (from type signature) that this cult is same as cult_
    val follower = personality.attractFollower(this)
  }

  case class Follower(leader: CultLeader,name: String)
}

trait Personality {
  def attractFollower(leader: Cult#CultLeader) = 
    leader.cult.Follower(leader.l,"Fred")   
} 

// Exiting paste mode,now interpreting.
defined trait Cult
defined trait Personality

这里是最终的解决方案,以正确的方式做你想要的:

trait Cult { cult_ =>
  case class CultLeader(personality: Personality) { 
    val cult: cult_.type = cult_
    val l: cult.CultLeader = this
    val follower = personality.attractFollower(this)
  }

  case class Follower(leader: CultLeader,name: String)

}

trait Personality {
  def attractFollower(leader: Cult#CultLeader) = 
    leader.cult.Follower(leader.l,"Fred")   
}  

// Exiting paste mode,now interpreting.
defined trait Cult
defined trait Personality

这里的意思是,cult_.type是路径依赖(投影).

(编辑:李大同)

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

    推荐文章
      热点阅读