像自我类型一样限制更高角度的路径依赖类型

时间:2017-09-29 20:10:29

标签: scala types generic-programming higher-kinded-types self-type

我正在尝试使用基于单个路径依赖类型的更简单版本替换使用2个类型参数和自我类型定义的类型。

我的问题是我无法表达相同的约束。我认为一个完整的例子将更容易理解。

class Attribute

// Test 1: Using a 2nd higher-kinded parameter and a self-type
// Advantage: Subclasses are constrained by the self-type to specify the "This" parameter correctly
// Drawback: Container1 has a 2nd type parameter and "AnyContainer1" type is really ugly
sealed trait Container1[+A <: Attribute, +This[+X <: Attribute] <: Container1[X, This]] { self: This[A] => }
class Foo[+A <: Attribute] extends Container1[A, Foo]
//class Bar[+A <: Attribute] extends Container1[A, Foo] // Won't compile :-)

object Container1 {
  // This is ugly...
  type AnyContainer1[+X <: Attribute] = F[X] forSome { type F[+Y <: Attribute] <: Container1[X, F] }
//  type AnyContainer1[+X <: Attribute] = Container1[X, AnyContainer1] // This doesn't compile :-(
}


// Test 2: Using path-dependent types
// Advantage: Container2 has a single type parameter and AnyContainer2 is easily expressed
// Drawback: The path-dependent parameter can be overridden in a bad way
sealed trait Container2[+A <: Attribute] {
  protected type This[+B <: Attribute] <: Container2[B]
  // Note that I need `This` to take a generic parameter in 
  // order to declare methods like `def foo[T]: This[T]` in subclasses.

}
class Bar[+A <: Attribute] extends Container2[A] {
  override protected type This[+X <: Attribute] = Bar[X]
}
class Baz[+A <: Attribute] extends Container2[A] {
  // Will compile even though `Bar != Baz`, I'd like to enforce This = Baz somehow...
  override protected type This[+X <: Attribute] = Bar[X]
}

object Container2 {
  type AnyContainer2[+X <: Attribute] = Container2[Attribute] // Easy :-)
}

在使用路径依赖类型保持清洁时,是否有更好的方法来约束This类型?使用Scala的下一个版本(现在为Dotty),存在类型将消失,并且应该用路径依赖类型替换,那么如何在没有存在类型的情况下实现它呢?

0 个答案:

没有答案