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 }
}
有人能评论一下这种方法和更高级类型之间的利弊吗?您愿意添加任何类型参数吗?:)谢谢关于类型检查器的任意性,你是完全正确的。我认为在很多情况下,等价性是不可判定的。