Why doesn't scalac think the method does not match the required tick signature?

Why is this not compiling?
The given error class SomeElement needs to be abstract, since method eval in trait Element of type [T <: Typed]=> scala.util.Try[T] is not defined

I do not understand why the eval method defined in SomeElement does not satisfy type restrictions.

As I understand it, eval should return something enclosed in Try , which are subclasses of Typed . Try is covariant in its type parameter. The implementation of eval in SomeElement returns a NumberLike and NumberLike subclasses of Typed . So what went wrong?

 import scala.util.Try trait Element { def eval[T <: Typed]: Try[T] } trait Typed case class NumberLike(n: Long) extends Typed case class SomeElement(n: Long) extends Element { def eval = Try { NumberLike(n) } } object app extends Application { println (SomeElement(5).eval) } 

Trying to add an explicit type parameter to eval in SomeElement will not help:

 case class SomeElement(n: Long) extends Element { def eval[NumberLike] = Try { NumberLike(n) } } 

Changing the definition of SomeElement to the above gives:

  found : <empty>.NumberLike required: NumberLike(in method eval) NumberLike(n) 

EDIT I would really like to know why this does not compile. Workarounds for this problem are helpful, but I really want to know what is going on here.

+8
types scala
source share
2 answers

A parameter of type T defined for the function, and not for the type of inclusion Element , it cannot be "deleted" by inheritance and must be stored in the override function ( http://www.scala-lang.org/files/archive/spec/2.11/ 05-classes-and-objects.html # class-members ).

Moving a type parameter into an Element definition makes it work as follows.

 trait Element[T <: Typed] { def eval: Try[T] } trait Typed case class NumberLike(n: Long) extends Typed case class SomeElement(n: Long) extends Element[NumberLike] { def eval = Try { NumberLike(n) } } 

Or using a member like:

 trait Element { type T <: Typed def eval: Try[T] } trait Typed case class SomeElement(n: Long) extends Element { type T = NumberLike def eval = Try { NumberLike(n) } } 
+2
source share

Since someone gave a decision, I'm trying to explain why.

In java, something like this is illegal:

 class A { <T> T f() {return null;} Object f() {return null;} } 

But in scala it is legal:

 class A { def f[T](): T = ??? def f(): Any = ??? } 

The main difference is that: scala process 2 methods with the same names and parameters, different if one of them has a type parameter and the other does not. (I think the signature of the scala method includes type parameters, right if I'm wrong :))

So, in your case, you cannot overwrite a method with a type parameter with the usual method (they have different signatures)

I'm not sure which one is better, personally I prefer the scala rule :)

0
source share

All Articles