Scala中的可交换特质

5
我想定义一个名为Swappable的特质,它有两个值x,y和一个swap方法。调用继承自Swappable的对象上的swap方法会返回另一个类型相同的对象,其x,y值已被交换。我的最佳实现如下:
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 }
  }
}

但这不是我想要的,因为 swap 的返回类型是某个匿名类,而不是我最初使用的原始类,所以我会遇到以下错误:
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
                                                                        ^

我是否能做到我正在尝试做的事情?交换的正确类型签名是什么?

2个回答

7

我不知道该怎么做,但我认为了解你想要发生的事情可能会有所帮助。考虑一个类似于下面的类:

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

现在,如果你有f = Foo(1, 2),那么f.swap会给你一个x != zFoo吗?如果是这样,在Scala中没有办法创建这样的Foo。如果不是,那么"swap x and 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)
}

但我不确定。

非常好!你提出了一个很好的观点,即交换的概念通常不清楚。在我的情况下,我只会使用不包含额外值的case类Foo(x: T, y: T)扩展Swappable,但是Scala没有太多的方法来知道这一点。所以我想我会把swap方法的实现留给每个继承类(基本上就是通过额外的方法cons来实现)。做到这一点的关键(我之前没有想到)是向Swappable传递额外的类型参数A,这使得继承类可以指定返回类型应该是什么。谢谢! - davidsd

3
像这样的内容怎么样:

这是关于IT技术的内容:

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

对的,这与Owen的解决方案非常相似。 - davidsd
1
仅供参考,此问题称为“MyType”:http://www.scala-lang.org/node/6649(Scala中还没有无样板答案)。 - Eric

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接