Scala 证明嵌套路径依赖类型成员的等价性

Scala 证明嵌套路径依赖类型成员的等价性,scala,dependent-type,Scala,Dependent Type,这是一个简化的案例,我完全愿意采用不同/更好的方法来实现这一点 trait Container { type T def data: List[T] } trait Transform { val from: Container val to: Container def xform: from.T => to.T } case class Identity(c: Container) extends Transform { val from = c val

这是一个简化的案例,我完全愿意采用不同/更好的方法来实现这一点

trait Container {
  type T
  def data: List[T]
}

trait Transform {
  val from: Container
  val to: Container
  def xform: from.T => to.T
}

case class Identity(c: Container) extends Transform {
  val from = c
  val to = c
  def xform = { t: from.T => t }
}
这会产生以下可预测误差:

<console>:12: error: type mismatch;
 found   : t.type (with underlying type Identity.this.from.T)
 required: Identity.this.to.T
         def xform = { t: from.T => t }
:12:错误:类型不匹配;
找到:t.type(具有基础类型标识.this.from.t)
必需:Identity.this.to.T
def xform={t:from.t=>t}
我们的目标基本上是要有一个转换来转换容器底层的对象,但是要能够说服类型检查器(没有到处都是可怕的强制转换)类型是相同的

以这种方式显示类型的等价性和关系的最佳方式是什么


正如我所说,完全可以重新构造代码,我在实际示例中保证这是为了真正的目的:)

因为
容器中的类型未公开,所以您无法推断
标识
类的任何内容。试想一下,如果您是从另一个库中使用它,那么如果您只是被赋予了
Identity
对象,就无法知道
xform
是什么类型。实际上,您可以用于
xform
的唯一定义如下:

def xform = { t: from.T => to.data.head }
您可以调用的唯一方法是使用.data.head中的

另一种方法是删除路径依赖类型,并使用更高级的类型:

  trait Container[T] {
    def data: List[T]
  }

  trait Transform[A, B] {
    val from: Container[A]
    val to: Container[B]
    def xform: A => B
  }

  case class Identity[A](c: Container[A]) extends Transform[A, A] {
    val from = c
    val to = c
    def xform = { t: A => t }
  }

我认为通用参数可能是描述这种模式的更简单的方法

但是,通过在两个
容器
实例上显式标识类型
T
,可以避免使用泛型参数:

case class Identity(c: Container) extends Transform {
  val from: Container { type T = c.T } = c
  val to: Container { type T = c.T } = c
  def xform = { t: from.T => t }
}
或者更简单:

case class Identity(c: Container) extends Transform {
  val from: c.type = c
  val to: c.type = c
  def xform = { t: from.T => t }
}
如果您同意只避免使用
Container
Transform
上的泛型参数,则可以通过执行以下操作使编译器确信这些类型是有效的:

case class Identity[U](c: Container { type T = U }) extends Transform {
  val from = c
  val to = c
  def xform = { t: c.T => t }
}
泛型参数
U
除了为
Container
参数上的
T
类型赋予另一个名称外,没有其他作用,但这就足够了


对我来说,所有这些解决方案实际上只是强调了当涉及到这些类型时,类型检查器的功能看起来是多么武断。我真的无法解释为什么它们是必要的或足够的。根据我的经验,使用泛型参数更容易预测(尽管它当然会更混乱)。

如果一个人一直被依赖类型所困扰,那么结构优化是一种丑陋但有效的纾困方法

abstract class ContainerRefiner {
  val container: Container
}

trait Container {
  type T
  def data: List[T]
}

trait Transform {
  val from: Container
  val to: Container
  def xform: from.T => to.T
}

case class Identity(c: Container) extends Transform {
  val refiner = new {val container: c.type = c} with ContainerRefiner
  val from = refiner.container
  val to = refiner.container
  def xform = { t: from.T => t }
}

有人能评论一下这种方法和更高级类型之间的利弊吗?

您愿意添加任何类型参数吗?:)谢谢关于类型检查器的任意性,你是完全正确的。我认为在很多情况下,等价性是不可判定的。