给定一些路径依赖类型的值,我如何获得“容器”的实例?

时间:2011-02-07 21:29:18

标签: scala scala-2.8

在代码中更容易解释:

class Bippy {
  val x = 42

  class Boppy {
    val y = "hello world"
  }

  val bop = new Boppy
}

val bip = new Bippy
val bop: Bippy#Boppy = bip.bop
然后将

bop提供给另一个方法,该方法需要从包含的x实例中找到值Bippy。这样做有什么神奇的咒语?

实例bop来自我无法控制的代码,因此在Boppy添加新方法不是一种选择。

2 个答案:

答案 0 :(得分:7)

你做不到。至少不是没有作弊。这是欺骗的方法。

def getOuter(bop : Bippy#Boppy) = 
   bop.asInstanceOf[{def Bippy$Boppy$$$outer() : Bippy}].Bippy$Boppy$$$outer()

显然,这非常依赖于今天scalac如何运作的细节,并且无法保证它将在明天起作用。

答案 1 :(得分:4)

正如詹姆斯所说,你做不到。他的作弊使我的眼睛流血,我建议做别的事情; - )

如果可以,我强烈建议修改bop的消费者。而不是给他们一个Bippy#Boppy的实例,给他们一对包含依赖类型的值和类型所依赖的值,

trait DependentPack {
  val bippy : Bippy
  val boppy : bippy.Boppy
}

val bip = new Bippy
val bop = bip.bop
val dep = new DependentPack { val bippy = bip ; val boppy = bop }
foo(dep)

def foo(dp : DependentPack) = {
  import dp._
  // use bippy ...
  // use boppy ...
}

请注意,这部分是缺少依赖方法类型的解决方法(通过添加-Ydependent-method-types或-Xexperimental命令行开关在scalac中启用)。如果我们拥有它们,那么我们可以放弃像DependentPack这样的人工制品并将上面的内容重写为

val bip = new Bippy
val bop = bip.bop
foo(bip)(bop)

def foo(bippy : Bippy)(boppy : bippy.Boppy) = {
  // use bippy ...
  // use boppy ...
}

毋庸置疑,我认为默认启用依赖方法类型是非常需要的。除非你非常小心,否则依赖类型的非平凡用途会在他们缺席的情况下给他们带来痛苦的世界。