如果绑定是抽象类型成员,则具有类型上限的高级类型构造函数不起作用



我想定义一个特征,该特征由上限R和更高种类的类型构造函数F[_]参数化,该构造函数仅接受作为R子类型的参数。我希望这个特征实现一个多态apply,可以将任何F[A]转换为Unit,前提是A <: R.

这段代码工作得很好:

import scala.language.higherKinds
// this is the trait with polymorphic `apply`
trait CoCone[R, F[_ <: R]] {
def apply[A <: R](x: F[A]): Unit
}
// Example:
sealed trait Domain
class Dom1 extends Domain
class Fnctr[X <: Domain]
val c = new CoCone[Domain, Fnctr] {
def apply[D <: Domain](x: Fnctr[D]): Unit = ()
}

(见下面关于命名的备注)

现在,如果我通过将其声明为某个模块的类型成员来抽象R,并在此模块中定义Fnctr[A <: R],如下所示:

import scala.language.higherKinds
trait CoCone[R, F[_ <: R]] {
def apply[A <: R](x: F[A]): Unit
}
trait ModuleIntf {
type AbstractDomain
class Fnctr[X <: AbstractDomain]
}
// No mention of an actual concrete `Domain` up to
// this point. Now let's try to implement a concrete
// implementation of `ModuleIntf`:
sealed trait Domain
class Dom1 extends Domain
object ModuleImpl extends ModuleIntf {
type AbstractDomain = Domain
val c = new CoCone[Domain, Fnctr] { // error [1], error [2]
def apply[D <: Domain](x: Fnctr[D]): Unit = ()
}
}

一切都坏了,我收到两条我不知道如何解释的错误消息:

[1] error: kinds of the type arguments (Domain,Main.$anon.ModuleImpl.Fnctr) do not 
conform to the expected kinds of the type parameters (type R,type F) in trait CoCone.
Main.$anon.ModuleImpl.Fnctr's type parameters do not match type F's expected parameters:
type X's bounds <: ModuleIntf.this.AbstractDomain are stricter than type _'s declared bounds <: R
val c = new CoCone[Domain, Fnctr] {
^
[2] error: kinds of the type arguments (Domain,Main.$anon.ModuleImpl.Fnctr) do not 
conform to the expected kinds of the type parameters (type R,type F) in trait CoCone.
Main.$anon.ModuleImpl.Fnctr's type parameters do not match type F's expected parameters:
type X's bounds <: ModuleIntf.this.AbstractDomain are stricter than type _'s declared bounds <: R
val c = new CoCone[Domain, Fnctr] {
^

我希望编译器能够识别出CoCone[Domain, Fnctr]ModuleImpl内部所有三个Domain = AbstractDomain = R都是相同的类型。

我在这里错过了一些明显的东西,还是scalac的限制 2.12.4 ?如果这是一个限制,有人在任何地方报告过吗?

编辑发现类似的东西:问题 #10186。是"一样"吗?不是"一样"吗?如果它是一个错误,我应该将其作为另一个测试用例吗?如果有人可以确认这不完全是我的错,和/或它确实与链接的问题密切相关,那将是可以接受的问题解决方案。

Edit2:正如@Evgeny所指出的,它不可能完全是问题10186,因为它在不同的编译器阶段失败(refchecks而不是typer)。


关于这个名字的评论:我在这里称这个特征CoCone,类似于通常定义的~>,可以被认为是一种自然的转变,某种程度上。在某种程度上,CoCone[Dom, Fctr]类似于Fctr ~> Const_Unit,但F域仅限于Dom的子类型。实际上,CoCone[R, F]是一个形状F的东西,可以通过网络发送某些R子类,但这并不重要,所以我把名称抽象出来。这个东西是一个相当常见的数学结构,没有什么太做作的,如果能编译就好了。

抽象类型成员的工作方法(在scalac 2.12.4中尝试):

import scala.language.higherKinds
trait CoCone[R, F[_ <: R]] {
def apply[A <: R](x: F[A]): Unit
}
trait ModuleIntf {
type AbstractDomain
type X = ({type XX <: AbstractDomain; type XXX = XX with AbstractDomain})
class Fnctr[X]
}
sealed trait Domain
case class Dom1() extends Domain
object ModuleImpl extends ModuleIntf {
type AbstractDomain = Domain
val f = new Fnctr[Dom1]()
val c = new CoCone[Domain, Fnctr] {
def apply[X](x: Fnctr[X]): Unit = ()
}
c(f)
}

想法取自问题 #4745 的评论。如果我没有遗漏任何东西,这应该相当于原始的不可编译方法。

当我发现当前的问题编译在不同的编译器阶段(refchecks)失败时 #10186 在typer上失败,但无论如何,在 #10186 中提到了补丁,我尝试了它,它修复了 #10186 本身,但仍然报告当前错误。

我会说它应该编译,但我没有发现任何类似于当前问题的问题,所以,假设它还没有报告编译器错误。

@Andrey评论后更新。

是的,太专注而无法获得可编译的版本,并且在特征上失去了上限。不好意思。

在进一步深入研究编译器内部后进行了更新

我调试了一些验证更高种类的类型(scala.reflect.internals.Kinds大约checkKindBoundsHK),看起来在检查Fnctr边界的那一刻,绑定类型树中没有信息AbstractDomainDomain的别名。如果我在object中将CoCone的第一个类型更改为AbstractDomain,而不是在树中,我看到它是Domain,但不是Fnctr界。

顺便说一句,修复 #10186 尝试解决类似问题,评估绑定参数asSeenFrom,正如我理解的那样试图获取具体类型,但是一旦在我们的例子中没有关于树中具体类的输入,就会返回AbstractDomain

相关内容

  • 没有找到相关文章

最新更新