How to define case classes with members with unrelated type parameters?

Given the definition of the class with the parameter bound type Animal[A <: String] , it seems that the Scala compiler does not output B <: String from Animal[B] . Can we conclude? How to help the compiler to draw a conclusion?

The following is a concrete example with class examples where the lack of this output is a problem.

Consider the following case class hierarchy:

 sealed trait Person[+T <: Person[T]] case class Student() extends Person[Student] case class Professor() extends Person[Professor] 

I need to define a case University class that I can create with a variable of type Person[_] , for example val p: Person[_] = Student() . I thought this would work with the following definition:

 case class University(p: Person[_]) 

But this does not compile with an error:

 type arguments [Any] do not conform to trait Person type parameter bounds [+T <: Person[T]] 

If I bind a parameter of the case University class type, it compiles (it also compiles with unlimited parameters if I drop the case keyword, but this is not an option in my case):

 case class BoundUniversity[P <: Person[P]](p: Person[P]) 

But this parameterized version cannot be created with an unlimited variable of type Person[_] :

 val p: Person[_] = Student() BoundUniversity(p) 

not compiled with:

 inferred type arguments [_$1] do not conform to method apply type parameter bounds [P <: Person[P]] 

The same error occurs for a method with an associated argument, for example:

 def general[P <: Person[P]](p: P) = println(p) 

therefore, this does not apply to class constructors.

Two questions:

  • The type Person defined using the restrictions of the parameters Person[+T <: Person[T]] , therefore each instance of this type is insured to comply with these limits: val p: Person[P] implies that P <: Person[P] ; or am I missing something? So, how can I explain this to the compiler so that it does not complain?

  • How / can I define a case class with members with an unrelated type parameter, for example case class University(p: Person[_]) ?

+6
source share
1 answer

Type X[_] unlikely to be what you want. When you use _ for a type, you basically say that you don't care what this parameter is because you will never need to use it.

In any case, this compiles. It can bite you along the way, existential types are the complex material that they are, but ...

 case class University(p: Person[t] forSome { type t <: Person[t] }) 
+2
source

Source: https://habr.com/ru/post/912478/


All Articles