12

何が機能するか(パートA)

タイプパラメータを持つトレイトがあるとします。

trait A[T]

実存型を使用してA、すべて同じであるsのコレクションを取得するメソッドを作成できTます。

def foo(as: Seq[A[X]] forSome { type X }) = true

これは以下とは異なることに注意してください。

def otherFoo(as: Seq[A[X] forSome { type X }]) = true

または同等のもの:

def otherFoo(as: Seq[A[_]]) = true

これらの場合、実存の範囲はの内部にあるSeqため、Asは異なるTsを持つことができます。私のオリジナルfoo(実存的なスコーピングを使用Seq)では、次のように問題ありません。

foo(Seq(new A[Int] {}, new A[Int] {}))

ただし、型パラメーターを異なるものにすると、コンパイルされません。

scala> foo(Seq(new A[Int] {}, new A[String] {}))
<console>:10: error: type mismatch;
 found   : Seq[A[_ >: java.lang.String with Int]]
 required: Seq[A[X]] forSome { type X }

              foo(Seq(new A[Int] {}, new A[String] {}))
                     ^

これはすべて非常に簡単です。

何が機能するか(パートB)

ここで、型パラメーターの代わりに型メンバーを持つ同様の特性があるとします。

trait B { type T }

B私はいくつかの指定されたものだけを取るメソッドを書くことができますT

scala> def bar[X](b: B { type T = X }) = true
bar: [X](b: B{type T = X})Boolean

scala> bar[Int](new B { type T = Int })
res5: Boolean = true

scala> bar[String](new B { type T = Int })
<console>:10: error: type mismatch;
 found   : java.lang.Object with B
 required: B{type T = String}
              bar[String](new B { type T = Int })
                          ^

繰り返しますが、これは期待どおりに機能します。

動作しないもの

上記と同等のものを書き込もうとするとfoo、タイプメンバーの場合、状況がおかしくなります。

scala> def baz(bs: Seq[B { type T = X }] forSome { type X }) = true
baz: (as: Seq[B{type T = X}] forSome { type X })Boolean

scala> baz(Seq(new B { type T = Int }, new B { type T = String }))
res7: Boolean = true

最後の行がコンパイルされることは私には意味がありません。すべてのタイプメンバーを同じにしたいと言った。私fooは、型パラメーターに対してこれを実行できることをbar示し、型メンバーに基づいて型を制約できることを示しています。しかし、私は2つを組み合わせることができません。

私はこれを2.9.2と2.10.0-M5で試しました。

動機

この質問はこれに触発されており、私の最初の考えは、実存型を使用することでした(繰り返しパラメータの型のスコープに実存型を取得することは不可能であると思われるという問題を2番目に取っておきます)。ここで便利です):

def accept(rs: Seq[RList[Int] { type S = X }] forSome { type X }) = true

ただし、これは実際には機能しません。上記の簡略化された例と同じ奇妙な結果が得られます。

4

2 に答える 2

3

私はついにそれを整理しました(少なくとも私はそう願っています)。逆にやってみましょう。特性を構築します。

scala> trait B {type T}
defined trait B

私たちは次のシーケンスを構築しようとしますB

scala> Seq(new B {type T = Int}, new B {type T = String})
res0: Seq[B{type T >: String with Int}] = List($anon$1@592b12d, $anon$2@61ae0436)

くそー、それは動作します!わかりました、私たちは平等ではありませんが、type Tそれで遊んでみましょう:

scala> res0 : (Seq[B {type T = X}] forSome {type X >: String with Int})
res1: Seq[B{type T = X}] forSome { type X >: String with Int } = List($anon$1@592b12d, $anon$2@61ae0436)

近いです。待てない、それは近くない、それはあなたがパラメータとして提案したものよりも良いbazです、私たちは生のタイプを提供するだけでなく、上限もあります!したがって、それをに明確に渡すことができbazます。これが、期待どおりに機能しない理由です。

于 2012-08-21T13:31:36.393 に答える
-1

あなたの例では:

scala> def baz(bs: Seq[B { type T = X }] forSome { type X }) = true

関数bazが特性BのSeqを取ることをコンパイラーに通知します。特性Bはたまたま型メンバーTを取りますが、コンパイラーに関する限り、Bの型メンバーTの型が同じでなくても、関数bazが特性BのSeqをとることはまったく問題ありません。関数が同じタイプのメンバーを持つ特性BのSeqを取得するようにしたい場合は、コンパイラーに次のように指示する必要があります。

scala> def baz[X](bs: Seq[B { type T = X }]) = true
baz: [X](bs: Seq[B{type T = X}])Boolean


scala> baz[Int](Seq(new B { type T = Int }, new B { type T = String }))
    <console>:10: error: type mismatch;
    found   : java.lang.Object with B
    required: B{type T = Int}
              baz[Int](Seq(new B { type T = Int }, new B { type T = String }))
                                               ^

scala> baz[Int](Seq(new B { type T = Int }, new B { type T = Int }))
res10: Boolean = true
于 2012-08-21T02:59:33.387 に答える