2009-07-26 7 views
8

InputOutputという2つのクラスがあり、それらが互いに接続されているとします。 Outputはあるタイプの値を生成し、Inputがそれらを消費します。この例ではスカラが型パラメータを推論できないのはなぜですか?

class Input[T] { 
    var output: Option[Output[_ <: T]] = None 
} 
class Output[T] { 
    var input: Option[Input[_ >: T]] = None 
} 

InputOutputペアは限りInput型パラメータがOutput型パラメータのスーパータイプであると値の同じ種類に動作しない場合、それは大丈夫です。両方のクラスの型パラメータは不変であることに注意してください。実際のバージョンでは、それは共位置および反位置の両方の位置で使用される。

val out = new Output[String] 
val in = new Input[AnyRef] 
connect(out, in) 

:私は以下のように、このメソッドを呼び出した場合、私は型エラーを取得

def connect[T](output: Output[T], input: Input[_ >: T]) = { 
    output.input = Some(input) 
    input.output = Some(output) 
} 

は私が Input/ Outputペア間のリンクを設定し他の場所 connect方法を持っていますエラーは次のとおりです。

test.scala:17: error: type mismatch; 
found : Output[String] 
required: Output[AnyRef] 
    connect(out, in) 
     ^

これを解決するには、型パラメータを書いてください(この場合、私はconnect[String]と書いていますが、コンパイラが私のためにこれを理解できるはずだと思います。タイプパラメータが自動的に推測されるように、どのようにしてconnectメソッドを変更できますか?


編集:今のところ、私はconnectOutputの方法を作ったので、それは自動的に型パラメータを取得します。これには、埋め込み表記out connect inを使用できるという追加の利点もありますが、デザインはやや厄介です。

私はまだコンパイラがこの動作を示す理由に興味があります。私はそれが型パラメータを推論することができるはずだと思う。これは実際に指定どおりに動作していますか?

+0

あなたは「同じ*種類の*値を操作しないでください」という意味でしたか? –

+0

Scalaのメーリングリストに質問してみましたか? – GClaramunt

答えて

6

あなたは時々あなたが複数のパラメータのリストを使用している場合、より良い結果が得られます:

def connect[T](output: Output[T])(input: Input[_ >: T]) = { 
    output.input = Some(input) 
    input.output = Some(output) 
} 

connect(out)(in) 

を...そして実際、この場合には、それが動作します。

+3

これはなぜ拡大できますか? *「時にはより良い結果が得られる」*非常に決定的に聞こえない! –

+6

悲しいことに、型推論は仕様化されておらず、ときどき確定的でもありません。 –

0

私は全く間違っているかもしれませんが、問題は入力と出力を結びつけるときです: 入力にはTのサブタイプに制限された出力がありますが、出力にはスーパータイプTであり、両方の条件を満たす唯一のタイプはTである。

Input[T] -> Output[ _ <: T ] 
Output[Q] -> Input[ _ >: Q ] 

あなたは出力(_ <とQを置き換える:T)と入力を作成するときに、あなたが得る:

入力[T]として

Input[T]->Input[ _ >: [_ <: T] ] 

同じ - >入力[_ <:T <:_]したがって

型ミスマッチ

+0

私の例では、StringとAnyRefは自分の制約を満たしています。 OutputはStringを生成し、Stringのいくつかのスーパータイプを使用するInputを必要とします。入力はAnyRefを消費し、AnyRefのサブタイプを生成するOutputを必要とします。 StringはAnyRefのサブタイプなので、制約は満たされます。 –

+0

問題は、接続に適切な型パラメータが1つあり、それが出力の型パラメータであることです。これを明示的に指定すると、うまく動作します。私がしなければ、それは入力の型パラメータを使用しようとすると、出力引数に型エラーが発生します。 –

+0

申し訳ありませんが、私は入力[_>:T]を接続[T]( – GClaramunt

0

実際にはスカラ型のinfereneでは "再帰"を扱うことができません。したがって、引数の型が他の引数との連鎖においてのみ推論できる場合、スカラは推論に失敗します。しかし、異なる引数リストのスカラを使用すると、f(a)(b)(c,d)はタイプリストをリストで推論しますので、それは良く動作します。

PS極端に簡潔ですが、手がかりを得ることができます。