scala - 不符合 lambda 类型的种类

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

使用“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/

相关文章:

haskell - 为什么我不能使用具有存在量化类型的记录选择器?

java - 如何在 jvm 上运行 scala 字节码?

java - Scala/Java语法,返回接口(interface)实现

java - 列表和 map 的通用集合?

c++ - 指针引用类型

java - 返回集合的通用方法给出不安全类型转换警告

haskell - 在没有 `Conkin.Traversable` 的情况下将值更改为 `unsafeCoerce` 中的索引

scala - 在 scala 中创建元组时类型绑定(bind)错误

scala - 在 Scala 中使用 C 联合

scala - 自类型可以与抽象类型一起使用吗?