种类不符合lambda类型

时间:2013-01-17 23:22:17

标签: scala types existential-type type-kinds partially-applied-type

类型“种类”有问题:

trait Sys[ S <: Sys[S]]
trait Expr[S <: Sys[S], A]
trait Attr[S <: Sys[S], A[_]]
def test[  S <: Sys[S]]: Attr[S, ({type l[x<:Sys[x]]=Expr[x,Int]})#l] = ???

失败
error: kinds of the type arguments (S,[x <: Sys[x]]Expr[x,Int]) do not conform
to the expected kinds of the type parameters (type S,type A) in trait Attr.
[x <: Sys[x]]Expr[x,Int]'s type parameters do not match type A's expected parameters:
type x's bounds <: Sys[x] are stricter than type _'s declared bounds >: Nothing <: Any
           def test[S <: Sys[S]]: Attr[S, ({type l[x<:Sys[x]]=Expr[x,Int]})#l] = ???
                                  ^

声明边界有什么问题?我是否需要将cr * ppy部分应用的类型带入trait Attr的类型构造函数中?为什么?我是否可以在不触及Attr的定义的情况下解决此问题?

我确实需要函数test中的边界才能使实现工作,但我希望将这些边界扩展到公共接口Attr。< / p>


注意:如果我使用类型成员(我不想要的话),它可以工作:

trait Attr[S <: Sys[S]] { type A[_]}
def test[  S <: Sys[S]]: Attr[S] { type A[S <: Sys[S]] = Expr[S, Int]} = ???

1 个答案:

答案 0 :(得分:4)

正如您所观察到的,在提供更高级别的类型参数时,您不能总是不匹配边界。有趣的是,它实际上是一个方差问题:

class A
class B extends A
trait NeedsNeedsA[T[S <: A]]
trait NeedsNeedsB[T[S <: B]]
trait NeedsA[S <: A]
trait NeedsB[S <: B]

def x: NeedsNeedsA[NeedsB] // fails
def y: NeedsNeedsB[NeedsA] // works

如果你认为一个较高的类型作为一个类型的函数,在它的参数的约束中是逆变的,这是有意义的。

有趣的是,在结构类型中,表面很像子类型,Scala不会给出相同的错误:

def t: MemberNeedsA { type T[S <: B] }
def u: MemberNeedsB { type T[S <: A] }

原因是结构类型有点像交叉点:

def s: MemberNeedsA with MemberNeedsB

可能是交叉点实际上并不存在,但Scala不会检查它。

好的,但这与你的问题不太相关。回到你的问题:我认为你有一个差异问题。您希望test为调用者提供AttrAttr拥有类型函数(A[_]),您想说, this Attr有一个类型函数,需要更具体的参数。我想你可以明白为什么你不应该被允许这样做 - 这就是你不能用一个需要更具体的论证的函数来代替一个需要更一般性论证的函数的原因。

此时我担心解决方案将取决于您希望Attr能够完成的任务。您需要弄清楚为什么在某些情况下需要限制类型参数比其他情况更多。如果在您的程序中概念上认为“某些Attr比其他trait Attr[S <: Sys[S], B[Y <: B[Y]], A[X <: B[X]]] def test[S <: Sys[S]]: Attr[S, Sys, L] = ... 更具限制性”,那么您可以定义:

A[_]

但解决方案将取决于{{1}}论证的限制意图。