Given a value of some path-dependent type, how can I get an instance of the "container"?

230 views Asked by At

It's more easily explained in code:

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 is then supplied to another method, which needs to find the value x from the containing instance of Bippy. What's the magic incantation to do so?

The instance bop comes from code that I don't control, so adding new methods to Boppy isn't an option here.

2

There are 2 answers

1
James Iry On BEST ANSWER

You can't. At least not without cheating. Here's how to cheat.

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

Obviously that's very dependent on details of how scalac works today and no guarantees that it will work tomorrow.

3
Miles Sabin On

As James said, you can't. His cheat makes my eyes bleed, and I suggest doing something else instead ;-)

I strongly recommend modifying the consumers of bop if you can. Rather than handing them an instance of Bippy#Boppy, hand them a pair comprising the value of the dependent type and the value that the type depends on,

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 ...
}

Note that this is in part a workaround for the lack of dependent method types (enabled in scalac by adding the -Ydependent-method-types or -Xexperimental command line switches). If we had them, then we could drop artefacts like DependentPack and rewrite the above as,

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

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

Needless to say, I think having dependent method types enabled by default would be highly desirable. Non-trivial uses of dependent types bring a world of pain with them in their absence unless you're very careful.