Why doesn't the input function work here?

This problem arose in the module that I am writing, but I made a minimal case that exhibits the same behavior.

class Minimal[T](x : T) { def doSomething = x } object Sugar { type S[T] = { def doSomething : T } def apply[T, X <: S[T]] (x: X) = x.doSomething } object Error { val a = new Minimal(4) Sugar(a) // error: inferred [Nothing, Minimal[Int]] does not fit the bounds of apply Sugar[Int, Minimal[Int]](a) // works as expected } 

The problem is that the compiler manages to define an internal parameter for Minimal ( Int ), but then sets another occurrence of T in Nothing , which obviously does not match apply . This is certainly the same T , since deleting the first parameter makes the second complaint that T is undefined.

Is there any ambiguity that means that the compiler cannot output the first parameter or is this an error? Can I get around this gracefully?

Additional Information: This code is a simple example of a syntax sugar attempt. The source code is trying to do |(a)| denoting the module a , where a is a vector. It is clear that |(a)| better than writing |[Float,Vector3[Float]](a)| but unfortunately I cannot use unary_| to make it easier.

Actual error:

arguments inferred type [Nothing, Minimal [Int]] do not correspond to the method to apply restrictions of the parameter type [T, X <: Sugar.S [T]]

+6
source share
2 answers

This is not a Scala compiler error, but it is, of course, a limitation of Scala type output. The compiler wants to determine the binding on X , S[T] before solving for X , but the reference mentions a variable of type T , which is therefore fixed in Nothing and comes from there. It does not review T times when X was completely resolved ... Currently, type inference always goes from left to right in this case.

If your example accurately reflects your real situation, then there is a simple fix,

 def apply[T](x : S[T]) = x.doSomething 

Here T will be deduced so that Minimal will correspond to S[T] directly, and not through an intermediate variable of a limited type.

Update

Joshua's solution also avoids the problem of type T inference, but in a completely different way.

 def apply[T, X <% S[T]](x : X) = x.doSomething 

desugars to,

 def apply[T, X](x : X)(implicit conv : X => S[T]) = x.doSomething 

Variables such as T and X can now be resolved independently (since T no longer mentioned in X bound). This means that X is output as Minimal immediately, and T is resolved as part of an implicit search for a value of type X => S[T] to satisfy the implicit argument conv . conforms in scala.Predef produces the values ​​of this form, and in the context ensures that, given an argument of type Minimal , T will be displayed as Int. You can view this as an instance of functional dependencies when working in Scala.

+9
source

There's some kind of weirdness with restrictions on structural types, try using view binding on S [T].

def apply[T, X <% S[T]] (x: X) = x.doSomething works fine.

+4
source

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


All Articles