在Scala中自我键入时自动混合api

时间:2016-05-02 12:39:20

标签: scala

这在scala中有些出乎意料(或者我的期望是错误的)。以下是一些示例代码:

trait A
trait B

trait HasA { def foo: A }
trait HasB { def foo: B }

到目前为止很好,然后我做了

scala> trait HasBoth extends HasA with HasB
<console>:11: error: overriding method foo in trait HasA of type => A;
 method foo in trait HasB of type => B has incompatible type
       trait HasBoth extends HasA with HasB

好吧,我看到了错误。这说得通。

但是后面出现了混乱:

trait Wrapper[T] { def get: T }
trait HasBoth2 { self: Wrapper[HasA with HasB] => def bar = get.foo }

我觉得这很疯狂。如果我们检查bar的类型,B。如果我们翻转订单,使约束为HasB with HasA,则barA

所以我们在这里有些不一致。我希望其中任何一个:

  1. HasA with HasB自动生成{ def foo: A with B },或
  2. HasBoth2会产生类型不兼容错误。
  3. 请妥善解释这种不一致,或者它是一种类型系统错误。

    更新

    trait HasBoth3 extends HasA with HasB { def foo: A with B }
    type Wrapped = Wrapper[HasBoth3]
    

    Wrapped将满足HasBoth2的约束。

1 个答案:

答案 0 :(得分:3)

这是预期的行为。这是斯卡拉的不健全的核心点之一。

SI-7278: Unsoundess in many guises

我在SI-7255中提供了一些解释,部分转载如下。

这似乎是类型系统的一个非常根本的失败,也许是dotty的动机的一部分。

抽象类型成员并不像通常所暗示的那样统一;他们只能被提炼。在这种情况下,这意味着创建一个类型,它是B与其自身类型的交集,即B与A的交集。交叉类型的创建假设它只能使用最后的C&#39;在线性化中,由于编译将在重新检查中失败,除非最后一个&#39; C&#39;是对任何早期版本的改进。

这个系统因自我类型而崩溃,因为一个类认为自己具有声明的类和声明的自身类型的交集。带有Y的X或带有X的Y可能是有效的实例化;没有先验的方法可以知道&#34; last&#34;成员C.

有关更多颜色,请参阅我对SI-7472的最新评论。