使用“kinds”类型时遇到问题:
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
中的边界才能使实现正常工作,但我不想希望将这些边界扩展到公共(public)接口(interface) Attr
.
注意:如果我使用类型member(我不想要的),它会起作用:
trait Attr[S <: Sys[S]] { type A[_]}
def test[ S <: Sys[S]]: Attr[S] { type A[S <: Sys[S]] = Expr[S, Int]} = ???
最佳答案
正如您所观察到的,在提供更高种类的类型参数时,您不能总是不匹配边界。有趣的是,这实际上是一个方差问题:
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
向调用者返回一个 Attr
,并且 Attr
拥有一个类型函数 (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[_]
参数的限制的含义。
关于scala - 不符合 lambda 类型的种类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14389972/