6

我正在尝试使用非常通用的类型参数参数化一些方法。

例如,在 REPL 中我首先定义:

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

直观地说,以下方法接受一个 Term 和一个 FunctionalTerm,并返回类型为传递的 term 类型的最小上限和 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)

尝试ex2在 REPL 中定义会出现以下错误:

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的 相同,ex1但使用T1T2交换,我不明白是错误的,或者如何修复它。

任何帮助将不胜感激!

更新

最小的上限是红鲱鱼。这个例子可以进一步提炼。

可以在 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签名中未使用的参数会有这种效果?

4

2 回答 2

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 = C@4ceeb514

请注意推断的结果类型(相当于R原始更复杂定义的 )......它是andA的 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 = C@522ddcec 
于 2012-05-16T19:15:15.497 回答
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]- 特别是FunctionalTerm. FunctionalTerm是一个类型构造函数 * -> *,但是该方法需要*在这个位置有一个类型。

我会说这(可能)是一个错误,因此您应该将其提交给 scala-user 邮件列表(在提出票证之前) - Adriaan MoorsMiles Sabin更有可能对我是否有详细的答案米对。

于 2012-05-16T18:20:18.057 回答