如何声明一个特征等同于给定类型参数的另一个通用特征?

How to state one trait is the equivalent of another generic trait for a given type parameter?

我有一个通用特征

trait MyTrait[T] {

    def apply(t: T): T

    def compose(e: MyTrait[T]): MyTrait[T]
}

还有另一个为特定类型实现此特征的特征...

trait IntTrait extends MyTrait[Int] {

    override def compose(e: MyTrait[Int]): MyTrait[Int]
}

现在,尽管这不是什么大不了的事,但主要是美学问题;我希望能够说...

trait IntTrait extends MyTrait[Int] {

    override def compose(e: IntTrait): IntTrait
}

但这打破了 MyTrait 方法的契约,因为它承诺在 all MyTrait[Int] 上定义,而 IntTrait,就编译器所知,是只是 MyTrait[Int] 的一个适当子集。所以我想做的基本上就是告诉编译器 IntTrait IS MyTrait[Int]。换句话说,没有不是 IntTraits 的 MyTrait[Int]。

我想我可以通过

完成这个
trait IntTrait extends MyTrait[Int] {

    type IntTrait = MyTrait[Int]

    override def compose(e: IntTrait): IntTrait
}

哪个有效! ...有点,但是如果我尝试在其他地方使用它...

trait doesStuffWithIntTrait {

    def foo: IntTrait
}

然后在实现中,我得到了这样的错误...

Type mismatch, expected: IntTrait, actual: IntTrait#IntTrait

有什么想法吗?

Type mismatch, expected: IntTrait, actual: IntTrait#IntTrait(基于foo方法)这个错误意味着你的foo方法return类型是IntTraitclass类型,但您正在 return 使用 类型别名 IntTrait 类型 (IntTrait#IntTrait).

并且对于 IntTrait IS MyTrait[Int]. 不是真实的,IntTraitsubclassMyTrait[Int]

为了您的目的,也许您可​​以这样做:

  trait MyTrait[T] {
    type K <: MyTrait[T]
    def apply(t: T): T
    def compose(e: K): K
  }
  trait IntTrait extends MyTrait[Int] {
    type K = IntTrait
    override def compose(e: IntTrait): IntTrait
  }

So what I'd like to be able to do is basically tell the compiler that IntTrait IS MyTrait[Int]. In other words, that there are no MyTrait[Int]s that are not IntTraits.

这其实是两种截然不同的愿望。首先,您确实想要一个类型别名,但是您将它放在了错误的范围内。删除 trait IntTrait,添加

object MyTrait {
  type IntTrait = MyTrait[Int]
}

(如果您还没有 object MyTrait)并将其称为 MyTrait.IntTrait。您也可以将其放在 package object 中。

对于第二个,你无法说服编译器,但遵循@chengpohi 的解决方案(或类似的

trait MyTrait[T, K <: MyTrait[T]] {
  def apply(t: T): T
  def compose(e: K): K
}
trait IntTrait extends MyTrait[Int, IntTrait] {
  override def compose(e: IntTrait): IntTrait
}

) 接近。就其本身而言,它并不能阻止某人也声明 trait IntTrait2 extends MyTrait[Int, IntTrait2],但您可以使 MyTrait sealed.