9

Setとして定義されSet[A]ます。インバリアントパラメーターを取ります。共変引数を渡しているため、以下を実行すると期待どおりに機能します。

scala> val a = Set(new Object)
a: scala.collection.immutable.Set[Object] = Set(java.lang.Object@118c38f)

scala> val b = Set("hi")
b: scala.collection.immutable.Set[String] = Set(hi)

scala> a & b
<console>:10: error: type mismatch;
 found   : scala.collection.immutable.Set[String]
 required: scala.collection.GenSet[Object]
Note: String <: Object, but trait GenSet is invariant in type A.
You may wish to investigate a wildcard type such as `_ <: Object`. (SLS 3.2.10)
              a & b

しかし、以下は機能します:

scala> Set(new Object) & Set("hi")
res1: scala.collection.immutable.Set[Object] = Set()

上記のように、scala コンパイラーは型に変換Set("hi")されるSet[Object]ため、機能します。

ここで型推論は何をしていますか? 誰かが動作を説明する仕様にリンクしてもらえますか?それは一般的にいつ発生しますか? そのような場合にコンパイル時エラーをスローするべきではありませんか? 同じ操作タイプの 2 つの異なる出力として。

4

2 に答える 2

7

確かではありませんが、あなたが探しているものは言語仕様の「Local Type Inference」の下に記述されていると思います (この記事の執筆時点では、100 ページのセクション 6.26.4)。

ローカル型推論は、多相型の式に渡される型引数を推論します。eが[ a 1 > : L 1 <: U 1 , ..., a n >: Ln <: U n ] T型であり、明示的な型パラメーターが指定されていないとします。

ローカル型推論は、この式を型適用e [ T 1 , ..., T n ]に変換します。型引数T 1 , ..., T nの選択は、式が現れるコンテキストと期待される型ptに依存します。3つのケースがあります。

[ ... ]

eが値引数に適用されずに値として表示される場合、型引数は、式の型Tを期待される型ptに関連付ける制約システムを解決することによって推論されます。一般性を失うことなく、 Tは値型であると仮定できます。メソッド型の場合は、eta-expansion を適用して関数型に変換します。解くとは、次のような型パラメーターa iの型T iの置換σを見つけることを意味します。

  • 推論された型はどれもT iはシングルトン型ではありません

  • すべての型パラメータの境界が尊重されます。つまり、 i = 1, ..., n に対してσ L i <: σ a iおよびσ a i <: σ U iです。

  • 式の型は、期待される型、つまりσ T <: σ ptに準拠しています。

そのような置換が存在しない場合、コンパイル時エラーになります。いくつかの置換が存在する場合、ローカル型推論は、型変数a iごとに解空間の最小型または最大型T iを選択します。型パラメーターa iが式の型Tに反変的に現れる場合、最大の型T iが選択されます。他のすべての状況では、最小型T iが選択されます。つまり、変数が共変、非変量、または型 T にまったくない場合です。このような置換を、型Tの特定の制約システムの最適解と呼びます。

要するに: Scalac は、省略したジェネリック型の値を選択する必要があり、結果がコンパイルされるという制約の下で、可能な限り具体的な選択肢を選択します。

于 2013-08-03T06:23:48.873 に答える
3

式は、コンテキストが必要とするものに応じて、または のSet("hi")いずれかになります。(もちろん、 Aは有効な です。)これを書くと:scala.collection.immutable.Set[String]scala.collection.immutable.Set[Object]StringObject

Set(new Object) & Set("hi")

コンテキストが を必要Set[Object]とするため、それが推論される型です。しかし、これを書くとき:

val b = Set("hi")

コンテキストが指定されていないため、より具体的なタイプSet[String]が選択され、(予想どおり)型が正しくありませんa & b

于 2013-08-03T05:54:19.553 に答える