11

タイププロジェクションから正しいタイプを推測するためにScalaを使用するのに問題があります。

次のことを考慮してください。

trait Foo {
  type X
}

trait Bar extends Foo {
  type X = String
}

def baz[F <: Foo](x: F#X): Unit = ???

次に、以下が正常にコンパイルされます。

val x: Foo#X = ???    
baz(x)

ただし、以下はコンパイルされません。

val x: Bar#X = ???    
baz(x)

Scalaはの「基になる型String」を認識しますがx、である情報を失いましxBar#X。タイプに注釈を付けると正常に機能します。

baz[Bar](x)

Scalaに正しい型パラメーターを推測させる方法はありますbazか?
そうでない場合、それを不可能にする一般的な答えは何ですか?

4

2 に答える 2

2

プログラムは、コンテキストにこの暗黙の変換を追加することによってコンパイルされます。

implicit def f(x: Bar#X): Foo#X = x

この暗黙の変換はどの場合にも正しいのでF <: Foo、なぜコンパイラがそれ自体でそれを行わないのか疑問に思います。

于 2013-02-22T04:25:16.107 に答える
1

あなたもすることができます:

trait Foo {
    type X
}
trait Bar extends Foo {
    type X = String
}
class BarImpl extends Bar{
  def getX:X="hi"
}
def baz[F <: Foo, T <: F#X](clz:F, x: T): Unit = { println("baz worked!")}
val bi = new BarImpl
val x: Bar#X = bi.getX
baz(bi,x)

しかし:

def baz2[F <: Foo, T <: F#X](x: T): Unit = { println("baz2 failed!")}
baz2(x)

失敗する:

test.scala:22: error: inferred type arguments [Nothing,java.lang.String] do not conform to method baz2's type parameter bounds [F <: this.Foo,T <: F#X]
baz2(x)
^
one error found

基本的に、F <:FooはコンパイラにFはFooのサブタイプでなければならないことを伝えますが、Xを取得すると、特定のXがどのクラスから来ているのかわかりません。Xは単なる文字列であり、Barを指す情報を保持していません。

ご了承ください:

def baz3[F<: Foo](x : F#X) = {println("baz3 worked!")}
baz3[Bar]("hi")

また動作します。val x:Bar#X=???を定義したという事実 ただそれを意味します??? コンパイル時にBar#Xが発生する可能性のあるものに制限されます...コンパイラはBar#Xが文字列であることを認識しているため、xのタイプは他の文字列と同じ文字列です。

于 2013-02-08T21:59:17.937 に答える