2014-09-20 38 views
0

Scala中的以下预期行为或错误?Scala参数化通用参数

CASE 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] 

最小化参数的数量可能会变得很简单ify代码类型参数:类型T [t1] <: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编译器的功能。

+1

我不认为你可以,是'Y [_]'嵌套的更高层次的不同,需要提供的编译足够的证据表明你尊重该约束的约束:'类Z [ S [t1,t2] <:X [t1,t2],T <:Y [S]]'。 – 2014-09-20 07:12:18

+0

@Ende Neu:是的,但是Y [T]的约束是相同的。 T仍然有相同的界限。如果我不要求,我不认为有任何理由指定T.请看CASE 3.我刚刚添加了它。 – 2014-09-21 05:47:16

+0

不,'T'没有相同的界限,类中的'T'和第二种情况下的'T'是两个不同的'T',仅仅因为它们具有相同的字母并不意味着它们是相关的。 – 2014-09-21 06:48:05

回答

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 

答案上的情况:

CASE 1:

类延伸等级Y应完全满足T [T](具有一个PARAM)即,例如:

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

CASE 2:

由于@Ende NEU提到,满足额外的PARAM约束T [T1,T2]类Y的,它的工作:

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应该有一个PARAM。例如:

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

案例1:你说Y需要一个参数为1的类型,但是你给了它一个有两个类型的类型。

案例2:类似的,尽量Z[T <: Y[_[_,_]]]

案例3:你说B需要一个类型1个PARAM,但你有两个给了它一个类型。

无问题,键盘和椅子之间存在问题。实际上正在做什么?即给出例子,包括具体的实现,那么也许人们可以帮助更多。

+0

简短的回答并不总是意味着正确的答案。但谢谢你的尝试。答案1:您可以声明“type T [t1] <:X [t1,_]”。在通用参数声明中不做同样的主要障碍是什么?答案2:你有没有尝试你的建议? (“错误的顶部声明声明”)答案3:CASE 3表达式不涉及两个参数。事实上CASE 3是最奇怪的。似乎AExt满足约束T [t] <:A [t],其中t是Int。如果将泛型替换为抽象类型,那么将编译所有这些表达式而不会出错。 – 2014-09-21 16:42:34