Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swappable Trait in Scala

I want to define a Swappable trait with two values x,y and a swap method such that calling swap on an object inheriting from Swappable returns another object of the same type with x,y switched. My best so far is:

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

But this isn't what I want because the return type of swap is some anonymous class, instead of the original class I started with, so I get errors like:

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
                                                                        ^

Is it possible to do what I'm trying to do? What is the correct type signature for swap?

like image 255
davidsd Avatar asked Jan 12 '12 21:01

davidsd


2 Answers

I don't know how to do it, but I think maybe it would help to get a better idea of what exactly you want to happen. Consider a class like

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

Now, if you have f = Foo(1, 2), should f.swap give you a Foo where x != z? If so, there's no way within Scala to create a Foo like that. If not, what does it really mean to "swap x and y"?

Perhaps what you're really looking for is something like this:

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

But I'm not sure.

like image 169
Owen Avatar answered Nov 17 '22 12:11

Owen


What about something like that:

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)
}
like image 25
Eric Avatar answered Nov 17 '22 11:11

Eric