2012-05-16 67 views
6

我想参数化一些非常一般的类型参数的方法。斯卡拉类型:最小上界

作为一个例子,在REPL我首先定义:

trait Term 
case class FunctionalTerm[+T <: Term](t: T) extends Term 

直观地说,下面的方法以一个期限和一个FunctionalTerm,并返回一些与类型的最小上界通过术语的类型和FunctionalTerm的参数类型:

def ex1[T1 <: Term, T3 <: X, FunctionalTerm[T1] <: X, X <: R, R <: Term](t1: FunctionalTerm[T1], s: T3): R = sys.error("TODO") 

到目前为止,在REPL中这么好。

然后我定义ex2作为进行相同的操作,ex1一个方便的功能,但与输入参数交换:

def ex2[T2 <: Term, T3 <: X, FunctionalTerm[T2] <: X, X <: R, R <: Term](s: T3, t2: FunctionalTerm[T2]): R = ex1(t2,s) 

试图在REPL定义ex2提供了以下错误:

error: inferred type arguments [T2,T3,FunctionalTerm,T3,T3] do not conform to method ex1's type parameter bounds [T1 <: Term,T3 <: X,FunctionalTerm[T1] <: X,X <: R,R <: Term] 
     ex1(t2,s) 
     ^
error: type mismatch; 
found : FunctionalTerm[T2] 
required: FunctionalTerm[T1] 
     ex1(t2,s) 
      ^
error: type mismatch; 
found : T3(in method ex2) 
required: T3(in method ex1) 
     ex1(t2,s) 
       ^
error: type mismatch; 
found : R(in method ex1) 
required: R(in method ex2) 
     ex1(t2,s) 
      ^

我花了大约两天的时间试图找出解决方案,现在我完全陷入困境。我无法在Google上找到更多内容。

由于ex2类型参数列表相同的ex1T1T2交换,我不明白的是错的,或如何解决它。

任何帮助将非常感激!

更新

最小上界是一个红色的鲱鱼。该示例可以进一步提炼。

以下两个功能可以在REPL中定义而不会出现错误:

def ex1[T1 <: Term, FunctionalTerm[T1] <: Term](t1: FunctionalTerm[T1]): Term = sys.error("TODO: ex1") 
def ex2[T2 <: Term, FunctionalTerm[T2] <: Term](t2: FunctionalTerm[T2]): Term = ex1(t2) 

介绍额外的参数X似乎会导致问题。我可以定义在REPL如下:

def ex3[T1 <: Term, FunctionalTerm[T1] <: X, X <: Term](t1: FunctionalTerm[T1]): Term = sys.error("TODO: ex3") 

但尝试之后定义:

def ex4[T2 <: Term, FunctionalTerm[T2] <: X, X <: Term](t2: FunctionalTerm[T2]): Term = ex3(t2) 

给出了错误:

error: inferred type arguments [T2,FunctionalTerm,Nothing] do not conform to method ex3's type parameter bounds [T1 <: Term,FunctionalTerm[T1] <: X,X <: Term] 
     def ex4[T2 <: Term, FunctionalTerm[T2] <: X, X <: Term](t2: FunctionalTerm[T2]): Term = ex3(t2) 
                          ^
error: type mismatch; 
found : FunctionalTerm[T2] 
required: FunctionalTerm[T1] 
     def ex4[T2 <: Term, FunctionalTerm[T2] <: X, X <: Term](t2: FunctionalTerm[T2]): Term = ex3(t2) 
                           ^

所以,我想这个问题就变成了:为什么签名中未使用的参数X是否具有此效果?

+0

我忘了说,我使用Scala的2.10-M3。 –

+0

虽然你没有使用更高的类型:-) –

+0

@oxbow_lakes哦......我会更正 –

回答

5

我不确定你是否遇到了错误,但我确定你让你的生活变得更加困难。你可以依靠协方差和统一做一切为你努力工作,

scala> trait Term 
defined trait Term 

scala> case class FunctionalTerm[+T <: Term](t: T) extends Term 
defined class FunctionalTerm 

scala> def ex1[T <: Term](t1 : FunctionalTerm[T], s : T) : T = s 
ex1: [T <: Term](t1: FunctionalTerm[T], s: T)T 

scala> class A extends Term ; class B extends A ; class C extends A 
defined class A 
defined class B 
defined class C 
scala> ex1(new FunctionalTerm(new B), new C) 
res0: A = [email protected] 

注推断结果类型(即相当于原来的更复杂的定义的R)......这是A这是LUB的BC

现在被翻动的版本是微不足道,只是作品,

scala> def ex2[T <: Term](s : T, t1 : FunctionalTerm[T]) : T = s 
ex2: [T <: Term](s: T, t1: FunctionalTerm[T])T 

scala> ex2(new C, new FunctionalTerm(new B)) 
res1: A = [email protected] 
+1

事实证明,报告的行为不是一个错误。在原始示例中使用FunctionalTerm [T1] <:X和FunctionalTerm [T2] <:X声明了一个名为“FunctionalTerm”的方法类型参数,该参数与具有相同名称的案例类无关。不过,我将其标记为答案,因为提出的建议达到了我需要做的。 –

+0

呃! ...令人惊讶的是我和@oxbow_lakes都没有注意到! –

2

我打算简化你的例子(我使用2.9。1):

scala> trait Term; case class FunctionalTerm[+T <: Term](t: T) extends Term; 
defined trait Term 
defined class FunctionalTerm 

scala> def ex1[T1 <: Term, T3 <: X, FunctionalTerm[T1] <: X, X <: R, R <: Term](t1: FunctionalTerm[T1], s: T3): R = sys.error("TODO") 
ex1: [T1 <: Term, T3 <: X, FunctionalTerm[T1] <: X, X <: R, R <: Term](t1: FunctionalTerm[T1], s: T3)R 

现在宣布第二个方法:

scala> def ex2[T2 <: Term, T3 <: X, FunctionalTerm[T2] <: X, X <: R, R <: Term](s: T3, t2: FunctionalTerm[T2]): R = ex1(t2, s) 
<console>:11: error: inferred type arguments [T2,T3,FunctionalTerm,T3,T3] do not conform to method ex1's type parameter bounds [T1 <: Term,T3 <: X,FunctionalTerm[T1] <: X,X <: R,R <: Term] 
     def ex2[T2 <: Term, T3 <: X, FunctionalTerm[T2] <: X, X <: R, R <: Term](s: T3, t2: FunctionalTerm[T2]): R = ex1(t2, s) 
                                ^

可疑的事情(我)是推断类型[T2,T3,FunctionalTerm,T3,T3] - 尤其是FunctionalTermFunctionalTerm是一个类型的构造函数* -> *但该方法预计在此位置的类型为*

我会说,这是(大概)一个bug,因此你应该将其提交到斯卡拉用户邮件列表(抚养票前) - 阿德里安摩尔万里萨宾更可能有关于我是否正确的详细答案。

+0

非常感谢 - 我怀疑这是一个错误,但是我对类型的了解有限,这让我非常谨慎。当我解决问题时我会更新。 –