Question

I'm trying to use this kind of code:

trait Outer {
  type Inner

  def f(x:Inner) : Void 
}

object test {
  def apply(o: Outer, i : Outer#Inner) : Void = 
    o.f(i)
}

I got an error in the last but one line:

type mismatch; found : i.type (with underlying type Outer#Inner) required: o.Inner

If I change apply's signature to

def apply(o: Outer, i : o.Inner) : Void

then I got an error:

illegal dependent method type

Is it possible to get this piece of code work?

Was it helpful?

Solution

You can take advantage of method dependent types (see What are some compelling use cases for dependent method types? by example). This will require you to use 2 parameter lists:

trait Outer {
  type Inner
  def f(x:Inner): Unit 
}

object test {
  def apply( o: Outer )( i : o.Inner) { o.f(i) }
}

OTHER TIPS

But imo o.Inner is much uglyier than Outer#Inner. Would you explain, what the point of use former instead of latter? The compiler can do only static checks so o.Inner should be equal o.type#Inner which should be (statically) equal to Outer#Inner. Am I missing something?

Here is the reason. Imagine you had

class Outer1 extends Outer {
  type Inner = Int

  def apply(i: Int) { ... }
}

class Outer2 extends Outer {
  type Inner = String

  def apply(i: Int) { ... }
}

Should test.apply(new Outer1, "abc") compile? Obviously not, since it'll call Outer1.apply(String), which doesn't exist. But then, test.apply(new Outer1, 1) can't compile either (otherwise you are back to path-dependent types) and there is no way to use this apply at all!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top