2012-01-12 13 views
5

Quiero definir un rasgo Swappable con dos valores x,y y un método swap tal que llamar swap sobre un objeto que hereda de Swappable retornos otro objeto del mismo tipo con x,y conmutada. Mi mejor hasta ahora es:Trait Swappable en Scala

trait Swappable[T] { 
    val x: T 
    val y: T 
    def swap: Swappable[T] = { 
    val (a,b) = (x,y) 
    new Swappable[T] { val x=b; val y=a } 
    } 
} 

Pero esto no es lo que quiero, porque el tipo de retorno de intercambio es cierta clase anónima, en lugar de la clase original Empecé con, por lo que tengo errores como:

def direct[S<:Swappable[Int]](s: S): S = if (s.x > s.y) s else s.swap 
<console>:32: error: type mismatch; 
found : Swappable[Int] 
required: S 
     def direct[S<:Swappable[Int]](s: S): S = if (s.x > s.y) s else s.swap 
                     ^

¿Es posible hacer lo que estoy tratando de hacer? ¿Cuál es la firma de tipo correcta para el intercambio?

Respuesta

7

No sé cómo hacerlo, pero creo que tal vez ayude a tener una mejor idea de qué es exactamente lo que quiere que suceda. Considere una clase como

case class Foo(x: Int, y: Int) extends Swappable[Int] { 
    val z = x 
} 

Ahora, si usted tiene f = Foo(1, 2), debe f.swap darle una Foo donde x != z? Si es así, no hay forma dentro de Scala para crear un Foo así. Si no, ¿qué significa realmente "cambiar xey"?

Tal vez lo que realmente está buscando es algo como esto:

trait Swappable[A,T] { 
    this: A => 

    val x: T 
    val y: T 
    def cons(x: T, y: T): A 

    def swap = cons(y, x) 
} 

case class Foo(x: Int, y: Int) extends Swappable[Foo,Int] { 
    val z = x 

    def cons(x: Int, y: Int) = copy(x=x, y=y) 
} 

pero no estoy seguro.

+0

muy agradable! Señala que la noción de intercambio no está clara en general. En mi situación, solo extenderé 'Swappable' con las clases de casos' Foo (x: T, y: T) 'que no contienen valores adicionales, pero Scala no tiene mucha información para saberlo. Así que supongo que dejaré la implementación del método 'swap' para cada clase heredada (que es básicamente lo que haces, a través del método adicional' contras'). La clave para hacer esto (que no había pensado) es pasar el parámetro de tipo extra 'A' a 'Swappable', que permite que las clases heredadas dicten cuál debería ser el tipo de retorno. ¡Gracias! – davidsd

3

¿Qué pasa algo así:

trait Swappable[T] { 
    type A 
    val x: T 
    val y: T 

    def create(a: T, b: T): A 
    def swap = create(y, x) 
} 

case MySwappable[T](x: T, y: T) extends Swappable[T] { 
    type A = MySwappable 
    def create(a: T, b: T) = MySwappable(a, b) 
} 
+0

Correcto, esto es muy similar a la solución de Owen. – davidsd

+1

Solo como referencia, esta pregunta se denomina "MyType": http://www.scala-lang.org/node/6649 (y aún no hay una respuesta sin formato en Scala) – Eric

Cuestiones relacionadas