わかりました、それで、私は以前にこれについて尋ねました。理想的には、型を一貫して指定する方法を理解するのに役立つ一般的な答えを探していますが、その代わりに、特定の問題を解決する方法に落ち着きます。これまでのところ、各ソリューションにはさらに 3 つの問題があるようです。アプリケーション全体をここに置くことは避けようとしていますが、私の目標は、再帰的にパラメーター化された特性タイプのタイプをどこからでも便利な方法で参照する方法を見つけることです。その特性タイプの値を交換可能に使用できる自明でないプログラム。
したがって、ここにさらにサンプルコードがあります:
//trait file, shouldn't need to know about implementing class.
trait MyTrait[T <: MyTrait[T]] { self:T =>
val listOfT: List[T]
def getFirst:T
def getOne:T = if( !listOfT.isEmpty ) getFirst else self
}
case class Foo[A <: MyTrait[A]](i: MyTrait[A])
object MyTrait {
def doSomething
[T <: MyTrait[T], U[X <: MyTrait[X]] <: MyTrait[X]]
(t: U[T]): T = t.getFirst
def testMethod1
[T <: MyTrait[T], U[X <: MyTrait[X]] <: MyTrait[X]]
(something:Foo[T]):T=
//error! type mismatch. found:T, required: ?U[?T]
doSomething(something.i.getOne)
def testMethod2
[T <: MyTrait[T], U[X <: MyTrait[X]] <: MyTrait[X]]
(something:Foo[T]):T=
//error! type mismatch.
// found: something.i.type (with underlying type this.MyTrait[T]
//required: T
something.i
def testMethod3
[T <: MyTrait[T], U[X <: MyTrait[X]] <: MyTrait[X]]
(something:Foo[U[T]]):U[T]=
//error: type arguments [U[T]] do not conform to class
//Foo's type parameter bounds [A <: this.MyTrait[A]]
something.i.getOne
// this works! ...but aren't something.i.getOne and something.i the same type?
// why does testMethod2 fail if this works ?
// what if I want to have a method that might return something.i and might return
// soemthing.i.getOne? What would the interface for that look like?
def testMethod4
[T <: MyTrait[T], U[X <: MyTrait[X]] <: MyTrait[X]]
(something:Foo[T]):T=
something.i.getOne
def testMethod5
[T <: MyTrait[T], U[X <: MyTrait[X]] <: MyTrait[X]]
(something:Foo[U[T]]):U[T]=
//error: type mismatch;
//found: something.i.type (with underlying type this.MyTrait[U[T]]
// required: U[T]
something.i
}
//class file, shouldn't need to have MyTrait anywhere except 'extends' line.
//should be a usefull class on its own without adding the trait.
class MyClass extends MyTrait[MyClass] {
//the point of using the parameterized type is to be able to return of
//List[MyClass] here instead of List[MyTrait] without having to override
// some 'type' attribute in anything that uses the trait.
override val listOfT: List[MyClass] = List[MyClass](this)
override def getFirst: MyClass = listOfT.head
}
//some client code:
val mc = new MyClass
val foo = Foo(mc)
MyTrait.doSomething(foo.i)
//MyTrait.testMethod1(foo)
型パラメーターの使用方法を理解しました: [T <: MyTrait[T], U[X <: MyTrait[X]] <: MyTrait[X]] この質問への回答から: ケースクラスフィールドの再帰型パラメーター
私は基本的に同じことをもう一度尋ねていますが、問題をもう少し進めています。ここで、something.i は基本的に something.i.getOne と同じ型を持っていることがわかりますが、これらの型は同じ意味で使用することはできません。そのため、オブジェクトをさまざまな関数のパラメーターとして一貫して使用することはできません。something.i と something.i.getOne (実際にはおそらく同じオブジェクト) がコンパイラと型システムによって認識されるのと同じ型を持つように、このコードを機能させるにはどうすればよいでしょうか?
この特定の質問の要点は、サンプル コードの testMethod4 にあります。