2012-01-12 2 views
5

Я хочу, чтобы определить Swappable черта с двумя значениями x,y и swap метода, такие, что вызов swap на объекте наследует от Swappable возвращает другой объект тех же типа с x,y коммутации каналов. Мой лучший до сих пор:Swappable Тра в 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 } 
    } 
} 

Но это не то, что я хочу, потому что тип возвращаемого свопа некоторый анонимный класс, вместо оригинального класса я начал с, так что я получаю ошибки как:

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 
                     ^

Можно ли делать то, что я пытаюсь сделать? Какая правильная сигнатура типа для swap?

ответ

7

Я не знаю, как это сделать, но я думаю, что, возможно, это поможет лучше понять, что именно вы хотите. Рассмотрим класс как

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

Теперь, если у вас есть f = Foo(1, 2), должны f.swap дать вам Foo где x != z? Если это так, в Scala нет никакого способа создать Foo. Если нет, что это значит «поменять x и y»?

Возможно, что вы действительно ищете что-то вроде этого:

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) 
} 

Но я не уверен.

+0

Очень приятно! Вы хорошо понимаете, что понятие обкатки в целом неясно. В моей ситуации я буду расширять «Swappable» классами case «Foo (x: T, y: T)», которые не содержат дополнительных значений, но Scala не знает об этом. Поэтому я предполагаю, что я оставлю реализацию метода swap для каждого наследующего класса (что в основном вы делаете с помощью дополнительного метода 'cons'). Ключ для этого (что я и не думал) передает дополнительный параметр типа «A» на «Swappable», который позволяет наследовать классы, чтобы определить тип возвращаемого типа. Благодаря! – davidsd

3

А что-то вроде этого:

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

Правильно, это очень похоже на решение Оуэна. – davidsd

+1

Только для справки этот вопрос называется «MyType»: http://www.scala-lang.org/node/6649 (и в Scala нет ответа без шаблонов) – Eric

Смежные вопросы