Peter Schmitz
Peter Schmitz

Reputation: 5844

Type Refinement

How can I make the following work?

trait T {
  type I <: T
  def apply(i: I): I
}

class Foo[T0 <: T](t: T0) {
  def bar(x: T0) = t(x)
}
implicit def tofoo[T0 <: T](t: T0) = new Foo(t)

The bar line yields the error:

type mismatch; found : x.type (with underlying type T0) required: Foo.this.t.I

(One might argue why pimp and having bar doing the same as apply in T. But it´s because I reduced the problem. In my working code I have a Seq[T] as a parameter of bar.)

EDIT:

Due to the answer of @AlexeyRomanov I show an example (also reduced from working code) what also should work:

trait T {
  type I <: T
  def apply(i: I): I
}

class Foo[T0 <: T { type I = T0 }](val t: T0) {
  def bar(x: T0) = t(x)
  def test = "!"
}

implicit def tofoo[T0 <: T { type I = T0 }](t: T0) = new Foo(t)


trait TA extends T {
  type I = TA
}
case class TB() extends TA {
  def apply(i: I): I = i
}

println(TB().test) // ERROR: value test is not a member of TB

Upvotes: 1

Views: 1813

Answers (2)

Daniel C. Sobral
Daniel C. Sobral

Reputation: 297265

It doesn't work because it is not sound. Suppose it worked, then we could do this:

trait T {
  type I <: T
  def apply(i: I): I
}

class Foo[T0 <: T](t: T0) {
  def bar(x: T0) = t(x)
}

class TA extends T {
    type I = TB
    def apply(i: I): I = i
}

class TB extends T {
    type I = T
    def apply(i: I): I = i
}

val ta = new TA
val foo = new Foo(ta)
foo.bar(ta) // calls ta(ta)

But ta.apply expects an element of type TB, not TA!

So, basically, the code you wrote does not represent the type relationships you have in your mind.

Upvotes: 5

Alexey Romanov
Alexey Romanov

Reputation: 170805

class Foo[T0 <: T {type I = T0}](val t: T0) { 
  def bar(x: T0) = t(x) 
}

implicit def tofoo[T0 <: T {type I = T0}](t: T0) = new Foo(t)

Upvotes: 1

Related Questions