6

この問題は私が書いているモジュールで発生しましたが、同じ動作を示す最小限のケースを作成しました。

class Minimal[T](x : T) {
  def doSomething = x
}

object Sugar {
  type S[T] = { def doSomething : T }
  def apply[T, X <: S[T]] (x: X) = x.doSomething
}

object Error {
  val a = new Minimal(4)
  Sugar(a) // error: inferred [Nothing, Minimal[Int]] does not fit the bounds of apply
  Sugar[Int, Minimal[Int]](a) // works as expected
}

Minimal問題は、コンパイラが( )の内部パラメーターを把握することに成功しIntた後、他の出現をTtoNothingに設定することです。これは明らかに一致しませんapplyT最初のパラメーターを削除すると、2 番目のパラメーターが T が定義されていないと不平を言うため、これらは間違いなく同じです。

コンパイラが最初のパラメータを推測できないことを意味するあいまいさがありますか、それともバグですか? これをうまく回避できますか?

詳細情報: このコードは、シンタックス シュガーの試みの簡単な例です。元のコードは、 a がベクトルである|(a)|のモジュラスを平均化しようとします。書くよりもa明らかに優れていますが、残念ながらこれを簡単にするために使用することはできません。|(a)||[Float,Vector3[Float]](a)|unary_|

実際のエラー:

推論された型引数 [Nothing,Minimal[Int]] は、メソッド apply の型パラメーターの境界 [T,X <: Sugar.S[T]] に準拠していません

4

2 に答える 2

9

これは Scala コンパイラのバグではありませんが、Scala の型推論の制限であることは確かです。コンパイラは、 を解く前にX、の境界を決定しようとしますが、境界はこれまで制約のない型変数に言及しているため、それを修正してそこから処理を進めます。完全に解決された後は再訪しません...現在、この種の場合、型推論は常に左から右に進みます。S[T]XTNothingTX

あなたの例が実際の状況を正確に表している場合、簡単な修正があります。

def apply[T](x : S[T]) = x.doSomething

ここでは、中間の有界型変数を介するのではなく、直接準拠するTように推論されます。MinimalS[T]

アップデート

ジョシュアの解決策も type を推測する問題を回避しますTが、方法はまったく異なります。

def apply[T, X <% S[T]](x : X) = x.doSomething

脱糖、

def apply[T, X](x : X)(implicit conv : X => S[T]) = x.doSomething

型変数TXは、独立して解決できるようになりました (はの境界Tで言及されなくなったため)。Xこれは、が即座にX推論され、暗黙的な引数 を満たす型の値の暗黙的な検索の一部として解決されることを意味します。inはこの形式の値を生成し、in context は指定された type の引数が Int として推論されることを保証します。これは、Scalaで機能する機能依存関係のインスタンスと見なすことができます。MinimalTX => S[T]convconformsscala.PredefMinimalT

于 2012-04-27T08:28:35.023 に答える
4

構造型の境界には奇妙な点があります。代わりに、S[T] にバインドされたビューを使用してみてください。

def apply[T, X <% S[T]] (x: X) = x.doSomething正常に動作します。

于 2012-04-27T00:46:11.593 に答える