Scala参数化通用参数

时间:2014-09-20 06:52:44

标签: scala generics type-parameter

Scala中存在以下预期行为或错误吗?

案例1:

class X[T1, T2]
class XExt[T1, T2] extends X[T1, T2]
class Y[T[t1] <: X[t1, _]]
class YExt extends Y[XExt]

结果 错误:XExt采用两种类型参数:预期:一个

class YExt extends Y[XExt]
                     ^

但是以下运行正常:

class X[T1, T2]
class XExt[T1, T2] extends X[T1, T2]
class Y[T[t1, t2] <: X[t1, t2]]
class YExt extends Y[XExt]

最小化params的数量可以简化代码类型params: type T [t1]&lt;:X [t1,_]

案例2:

class X[T1, T2]
class Y[T[t1, t2] <: X[t1, t2]]
class Z[T <: Y[_]]

结果 错误:_ $ 1没有类型参数,预期:两个

class Z[T <: Y[_]]
               ^

但如果我不需要它们,如何避免定义Y参数?喜欢在:

class X[T1, T2]
class Y[T <: X[_, _]]
class Z[T <: Y[_]]

案例3:

trait A[T]
trait B[T[t] <: A[t]]
trait AExt extends A[Int]
trait BExt extends B[AExt]

结果 错误:AExt没有预期的类型参数:一个

trait BExt extends B[AExt]
                     ^

但是为什么编译器请求一个参数(如果它已经提供)?这似乎是一个矛盾。以及如何继承B?


在IntelliJ Scala插件和Eclipse Scala IDE中观察到这种行为。所以它可能是Scala编译器的功能。

2 个答案:

答案 0 :(得分:1)

案例1:你说Y采用一个带有1个参数的类型,但是你给它一个有两个类型的类型。

案例2:类似,请尝试Z[T <: Y[_[_,_]]]

案例3:你说B采用一个带有1个参数的类型,但你给它一个带有两个类型的类型。

没有错误,键盘和椅子之间存在问题。实际上该做什么?即举例,包括具体实施,然后人们可以提供更多帮助。

答案 1 :(得分:0)

误解的原因实际上是混合了抽象类型和泛型参数的概念。 错误的假设是类型参数和通用参数在约束规则中是相等的。见下文。 Z类的T1和T2是等价的。但是在ZExt中,它们可以用类XExt1和XExt2定义,它们具有不同数量的参数。 XExt2的第二个参数被忽略了。我所期望的是,使用泛型实现相同的逻辑将允许相同的语法。即Z1将接受XExt1以及XExt2(如Z中的T1和T2)。但它只接受XExt1。将XExt2作为参数放置会导致错误。

老实说还是不明白为什么不给出仿制品类型的自由。即为什么不让XExt2成为Z1的参数,允许编译器推断XExt2参数类型,只是忽略它的第二个参数。

class X[T1, T2]
class XExt1[T1] extends X[T1, Int]
class XExt2[T1, T2] extends X[T1, T2]

class Z {
    type T1[t] <: X[t, _]
    type T2[t] <: X[t, _]
}
class ZExt extends Z {
    type T1[t] = XExt1[t]
    type T2[t] = XExt2[t,_]
}

// But...
class Z1[T[t] <: X[t, _]]
class ZExt1 extends Z1[XExt1]
class ZExt2 extends Z1[XExt2] // Error: XExt2 takes two type parameters, expected: one

案件答案:

案例1:

扩展Y类的类应该完全符合T [t](有一个参数),例如:

class X[T1, T2]
class XExt[T1] extends X[T1, Int]
class Y[T[t1] <: X[t1, _]]
class YExt extends Y[XExt]

案例2:

由于@Ende Neu提到满足约束条件T [t1,t2]的额外参数,它完成了它的工作:

class X[T1, T2]
class Y[T[t1, t2] <: X[t1, t2]]
class Z[S[t1, t2] <: X[t1,t2], T <: Y[S]]

不幸的是,T [t1,t2]不能用@samthebest建议的下划线语法来描述。编译器警告“错误的顶级声明声明”:

class Z[T <: Y[_[_, _]]]

案例3:

与案例1中的问题相同.AExt应该有一个参数。例如:

trait A[T]
trait B[T[t] <: A[t]]
trait AExt[T] extends A[T]
trait BExt[T] extends B[AExt]