バインドされた型パラメーターを持つクラス定義が与えられた場合、Scala コンパイラーはからAnimal[A <: String]
推論しないようです。推論は許されますか?コンパイラが推論を行うのを助ける方法は?B <: String
Animal[B]
以下は、この推論の欠如が問題となるケース クラスの具体的な例です。
次のケース クラス階層を考えてみましょう。
sealed trait Person[+T <: Person[T]]
case class Student() extends Person[Student]
case class Professor() extends Person[Professor]
たとえばUniversity
、型の変数でインスタンス化できるケース クラスを定義する必要があります。これは次の定義で機能すると思いました。Person[_]
val p: Person[_] = Student()
case class University(p: Person[_])
しかし、これはエラーでコンパイルに失敗します:
type arguments [Any] do not conform to trait Person's type parameter bounds [+T <: Person[T]]
ケースクラスの型パラメーターをバインドすると、University
コンパイルされます(キーワードをドロップすると、無制限のパラメーターでもコンパイルされますcase
が、これは私の場合のオプションではありません):
case class BoundUniversity[P <: Person[P]](p: Person[P])
しかし、このパラメータ化されたバージョンは、タイプ の無制限の変数でインスタンス化することはできませんPerson[_]
:
val p: Person[_] = Student()
BoundUniversity(p)
コンパイルに失敗します:
inferred type arguments [_$1] do not conform to method apply's type parameter bounds [P <: Person[P]]
次のようなバインドされた引数を持つメソッドでも同じエラーが発生します。
def general[P <: Person[P]](p: P) = println(p)
したがって、これはクラス コンストラクターに固有のものではありません。
2 つの質問:
型
Person
はパラメータ bounds で定義されるためPerson[+T <: Person[T]]
、この型の各インスタンスはこれらの境界を尊重することが保証されます。または私は何かを逃していますか?では、コンパイラが文句を言わないようにするにはどうすればよいでしょうか?val p: Person[P]
P <: Person[P]
のようなバインドされていない型パラメーターを持つメンバーでケースクラスを定義する方法/できます
case class University(p: Person[_])
か?