Is a linked perspective incompatible with a top binding?

I have a method that accepts Comparable and returns Comparable and wraps another method that does the same:

def myMethod[T <: Comparable[T]](arg: T): T = otherMethod(arg) def otherMethod[T <: Comparable[T]](arg: T): T = arg 

This is a compilation, but it does not allow me to call myMethod with Int or any other type that requires an implicit conversion to implement Comparable. As far as I understand, the boundaries of the representations are intended to solve this problem, but using a view constraint

 def myMethod[T <% Comparable[T]](arg: T): T = otherMethod(arg) 

I get a compiler error:

arguments inferred type [T] do not match the method for evaluating the parameters of the method otherMethod [T <: java.lang.Comparable [T]]

So far, the only workaround I came up with is to use a second type parameter and between the two:

 def myMethod[T <% Comparable[T], U <: Comparable[U]](arg: T): T = otherMethod(arg.asInstanceOf[U]).asInstanceOf[T] 

It works, but it is ugly. Is there a better way?

+4
source share
1 answer

Will one of the following be done?

  • Make the binding of the T representation consistent in both methods,

     def otherMethod[T <% Comparable[T]](arg: T): T = arg def myMethod[T <% Comparable[T]](arg: T): T = otherMethod(arg) 
  • Introduce a new parameter of type U <: Comparable[U] and an implicit conversion from T to U ,

     def otherMethod[T <: Comparable[T]](arg: T): T = arg def myMethod[U <: Comparable[U], T <% U](arg: T): U = otherMethod(arg) 

The problem with your version is that T <% Comparable[T] converts T to type Comparable[T] , but this does not satisfy the recursive type T <: Comparable[T <: Comparable[T <: ...]] ( pseudo code) that otherMethod expects.


Update To use either otherMethod or myMethod with Scala Int , you need to help the inferencer type a bit.

 myMethod(2) // Int value types don't implement Comparable myMethod(2: java.lang.Integer) // Apply implicit conversion (Int => java.lang.Integer) 

Update 2. In the comments, you said you were ready to make myMethod little ugly in order to improve type inference on the call site. Here is the way

 def myMethod[U <: Comparable[U], T](arg: T) (implicit ev1: T => U, ev2: T => Comparable[U]): U = otherMethod(arg) myMethod(2) // returns java.lang.Integer(2) 

The trick is to use two implicit conversions: ev1 actually used, and ev2 is only for type inference. The latter requires Scala to search for its implications for a conversion of type Int => Comparable[U] . In this case, you can find only one such transformation that fixes U = java.lang.Integer .

By the way, try compiling this code with scalac -Xprint:typer . You will see that the same implicit, Predef.int2Integer , is used for the ev1 and ev2 .

Side note: it is better to avoid asInstanceOf butts, as they damage the sound of a Scala system.

+6
source

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


All Articles