Tipo Refinamiento

¿Cómo puedo hacer que funcione lo siguiente?

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)

La bar línea produce el error:

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

(Se podría argumentar por qué proxeneta y tener bar haciendo lo mismo que apply in T. Pero es porque reduje el problema. En mi código de trabajo tengo una Seq [T] como parámetro de bar.)

EDIT:

Debido a la respuesta de @AlexeyRomanov, muestro un ejemplo (también reducido del código de trabajo) que también debería funcionar:

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

preguntado el 06 de noviembre de 11 a las 15:11

2 Respuestas

No funciona porque no es sonido. Supongamos que funcionó, entonces podríamos hacer esto:

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)

Pero ta.apply espera un elemento de tipo TBno, TA!

Entonces, básicamente, el código que escribió no representa el tipo de relaciones que tiene en su mente.

respondido 06 nov., 11:23

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)

respondido 06 nov., 11:19

Estoy confundido en este momento: ¿tengo razón en que su solución dice T0.I = T0? Pero que si I debería ser un subtipo de T como se indica en trait T? (Quizás no lo he dejado tan claro en mi pregunta) ¿Todavía es posible? - Peter Schmitz

Entonces eso es lo que debe requerir: T {type I >: T0} - Alexey Romanov

Si el único requisito es que I ser un subtipo de T entonces, obviamente, no es posible: es por eso que su definición original no se compila. Solo considera las definiciones trait TA extends T y class TB() extends T { type I = TA; def apply(x: TA) = x}. Que debería new Foo[TB](new TB).bar(new TB) ¿hacer? - Alexey Romanov

Quiero asegurarme de que el parámetro x of bar tiene el mismo tipo subyacente I as t in Foo. Entonces los tipos de algunos T para Foo y de alguna otra T para bar El parámetro puede ser diferente, pero su I tiene que ser el mismo. Por ejemplo, dos subclases Tb y Tc de mi arriba Ta tener lo mismo I pero son de diferentes tipos mientras envuelven Foo. - Peter Schmitz

Bueno, si x es solo algo T con un subyacente dado I, entonces t(x) no tiene sentido. - Alexey Romanov

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.