3

I have this kind of code

trait Outer1 {
  type Inner1
}

trait Outer2 {
  type Inner2

  val ev: Outer1#Inner1 =:= Inner2

  def f: Outer1#Inner1
}


object Main {

//  My Problem here  
//  def test1(o2: Outer2): o2.Inner2 =
//    o2.f                                  // <- type mismatch

  def test2(o2: Outer2): o2.Inner2 =
    o2.ev.apply(o2.f)
}

Is there any chance to make test1 work? Why Scala compiler can't see ev and apply it implicitly?

Artem Pelenitsyn
  • 2,149
  • 17
  • 32

1 Answers1

3

Two problems: First of all, your evidence parameter is not implicit, and therefore also not implicitly found by the compiler:

trait Outer1 {
  type Inner1
}

trait Outer2 {
  type Inner2

  implicit val ev: Outer1#Inner1 =:= Inner2

  def f: Outer1#Inner1
}

Second problem, a member of a value is not part of the standard implicit lookup scope. So you need to import that:

object Main {
  def test1(o2: Outer2): o2.Inner2 = {
    import o2.ev  // !
    o2.f
  }
}

EDIT: Abstract type checking notwithstanding, if I'm not mistaken, there is no way you can actually materialise Outer2, because how are you going to give evidence that its member Inner2 equals Outer1#Inner1 when Inner1 is abstract? That is why I am asking for the concrete scenario, because from this abstract layout, I'm not sure you are going to get anywhere.

As far as I can see, the evidence would only make sense for a dependent type, e.g.

trait Outer1 {
  type Inner1
  def bar: Inner1
}

trait Outer2 {
  type Inner2
  val outer1: Outer1 { type Inner1 = Inner2 }

  def foo: Inner2 = outer1.bar
}
Community
  • 1
  • 1
0__
  • 64,257
  • 16
  • 158
  • 253
  • Well, the first problem is a my fault, I agree. The second one really makes me sad: I don't see any valuable difference between explicit usage of `ev` (like in `test2`) and explicit import of `ev` (like in your answer). I consider this as a design flaw in an implicits' lookup mechanism. – Artem Pelenitsyn Jun 02 '13 at 18:04
  • 1
    The solution is to place your implicits where the compiler looks for them, hence the link. Typically this will be companion objects, but the actual solution depends a lot on what your use case will be like, from the example it's a bit difficult to judge. Perhaps you formulate the problem the other way round—state more abstractly what you are trying to achieve, and then ask how to get there. – 0__ Jun 02 '13 at 19:33
  • I just want my method inside `Outer2` which is bound to return `Inner2` object to use inside itself some code which really returns `Inner1`. I don't want any additional qualification/importing to point compiler that there is an evidence, that `Inner1 =:= Inner2`: the fact that I stated through `ev` value. I want to find out where to place `ev` to be sure that compiler will find it without additional help. – Artem Pelenitsyn Jun 03 '13 at 14:30