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

2

5

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.

Snug answered 7/2, 2011 at 21:29 Comment(0)
D
7

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.

Deface answered 7/2, 2011 at 22:22 Comment(1)
It's the solution I'm using already :) But as it seems there's no better way, you get the green tick, bleeding eyes and all!Snug
N
4

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.

Network answered 7/2, 2011 at 23:32 Comment(3)
I guess I took his problem as "I have a Boppy that came from somewhere else and I need to get its Bippy". If something like Miles' solution is possible then by all means do this.Deface
Sadly, I don't have access to bip either. Just bop and an unruly type signature...Snug
Still, good call on the dependent typing! It deserves to get a bit of an airing out from time to time.Snug

© 2022 - 2024 — McMap. All rights reserved.