要するに: 以下はコンパイルされません (以下の理由)。どうすれば動作させることができますか?
trait Simulator {
type CM[T]
def useCM(v: CM[_])
}
case class CMH[S <: Simulator,T](cm: S#CM[T])
class SimIterator[S <: Simulator](val sim: S, val cmhs: Seq[CMH[S,_]]) {
cmhs foreach { cmh => sim.useCM(cmh.cm) }
/*
compile time error:
type mismatch; found : cmh.cm.type (with underlying type S#CM[_$2]) required:
SimIterator.this.sim.CM[_] Note: _$2 <: Any (and cmh.cm.type <: S#CM[_$2]),
but type CM is invariant in type T. You may wish to define T as +T instead.
(SLS 4.5)
*/
}
構造の背後にある考え方は、後者が一般的なタスクを処理する場所から固有の動作をCMH
隠すことです。のインスタンスを持たずに、値を強制的に正しい型にするために使用されます。T
SimIterator
S
CMH
Simulator
では、foreach
に関連するサブタイプの問題があるようCM
です。S#CM
が必要な具体的なタイプの場合sim.CM =:= S#CM
。ただし、次の点を見てください。
object Test extends Simulator {
type CM[T] = Option[T]
def useCM(v: CM[_]) = println(v)
def mkCM[T]: CM[T] = None
CMH[Simulator,AnyRef](mkCM[AnyRef])
}
これで、 any と一緒CMH
に a に渡すことができます。したがって、どうやら の入力は十分に制限的ではありません。どのように表現 (および使用) できますか?SimIterator
Simulator
SimIterator
S =:= sim.type
アップデート
これは機能しますが、コンストラクターで使用することはできません (不正な依存メソッド タイプ: パラメーターが同じセクションまたは前のセクションの別のパラメーターの型に表示されます)
class SimIterator(val sim: Simulator) {
def doIt(cmhs: Seq[CMH[sim.type,_]]) {
cmhs foreach { cmh => sim.useCM(cmh.cm) }
}
}
上の例は機能しますが、私が望むものではありません。cmhs
建設時に渡す必要があります。