6

非常に一般的な型パラメーターを使用して、いくつかのメソッドをパラメーター化しようとしています。

例として、REPLで最初に定義するのは次のとおりです。

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

直感的には、次のメソッドは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)
            ^

私は解決策を見つけるために約2日間を費やしましたが、今では完全に行き詰まっています。Googleでこれ以上何も見つかりません。

の型引数リストはex2と同じですex1が、T1T2交換されているので、間違っているか、修正方法がわかりません。

どんな助けでも大歓迎です!

アップデート

最小の上限は赤いニシンでした。例はさらに蒸留することができます。

次の2つの関数は、エラーなしで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推測された結果タイプ(元のより複雑な定義のと同等)に注意してください...これはとAのLUBです。BC

これで、反転バージョンは簡単で、Just Works、

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

次に、2番目のメソッドを宣言します。

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型コンストラクター ですが、メソッドはこの位置* -> *に型を想定しています。*

これは(おそらく)バグであるため、(チケットを発行する前に)scala-userメーリングリストに送信する必要があります-AdriaanMoorsMilesSabinは、私がm右。

于 2012-05-16T18:20:18.057 に答える