Exchange the upper bound of a parameter for a proof parameter

I want to relax the restrictions on the parameter of the type of features and instead impose them on the method in the form of a parameter of evidence. Given some skeletal customization:

trait State[Repr] object Observer { def apply[Repr <: State[Repr]](reader: Reader[Repr]): Observer[Repr] = new Observer[Repr] {} } trait Observer[A] trait Reader [A] 

It works:

 trait StateX[Repr <: StateX[Repr]] extends State[Repr] { protected def reader: Reader[Repr] def observe: Observer[Repr] = Observer(reader) } 

And this is not so:

 trait StateY[Repr] extends State[Repr] { protected def reader: Reader[Repr] def observe(implicit ev: Repr <:< State[Repr]): Observer[Repr] = Observer(reader) } 

With the message "inferred type arguments [Repr] do not conform to method apply type parameter bounds [Repr <: State[Repr]]" . "inferred type arguments [Repr] do not conform to method apply type parameter bounds [Repr <: State[Repr]]" Since ev data attests to this conformation, I wonder how StateY can be fixed.

+6
source share
2 answers

Your problem is that even if the data of the form A <:< B implies that a value of type A can be converted to a value of type B , this does not mean A <: B ... indeed, the main reason for using a type constraint or view binding, but not a limitation of the usual type, it lies precisely in the fact that such a subtype relation is not satisfied.

Therefore, the restriction in StateY , Repr <:< State[Repr] not enough to perform the evaluation of Repr <: State[Repr] using the Observer apply method. Given that you want to reduce the constraint on a parameter of type StateX , the only option is to relax the constraint on a parameter of type of the apply method, respectively. This gives you something like the following, using view binding instead of the usual type binding,

 object Observer { def apply[Repr <% State[Repr]](reader : Reader[Repr]) : Observer[Repr] = new Observer[Repr] {} } 

or alternatively

 object Observer { def apply[Repr](reader : Reader[Repr]) (implicit ev : Repr <:< State[Repr]) : Observer[Repr] = new Observer[Repr] {} } 

if you prefer to use restrictions in everything.

+6
source

The evidence suggests that a Repr can be converted to State[Repr] . It does not say anything about what can be done using Reader [Repr].

There is no general method (independent of T) to convert T [A] to T [B] provided A => B. This may be possible for covariant T, but there is no such thing in this language.

+5
source

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


All Articles