9
votes

Reading the Scala by Example book and there is this example when Martin explains type bounds on page 54:

trait Set[A <: Ordered[A]] {
  def incl(x: A): Set[A]
  def contains(x: A): Boolean
}

and

trait Set[A <% Ordered[A]] ...

further on page 55. He also says that the <:/<% is the only change required for trait Set in order to demonstrate the type bounding possibilities.

However, when I repeat the example with my own code, the IDE complains that traits may NOT have view bounds, only type bounds. Changing the trait keyword to abstract class or changing the view bound to type bound helps. Is this a mistake in the book?

1
there was a change in the spec after "Scala by Example" was written. See this discussionPaolo Falabella
Thanks for pointing out! However I think that it is not good that complexity of implementation influences the language. There is no logical explanation of why traits may not have upper bounds.noncom
Traits can have upper bounds. They cannot have context and view bounds, because these are constructor parameters, and traits can't have constructor parameters.Daniel C. Sobral
Thank you, Daniel, yes it appears to be that these constructions are merely syntactic sugar and the explanation lies in the real underlaying language syntax. However, I am curious now, could you please explain or point to a source that explains, how could that be, that this feature was supported before? How many more changes like this are planned/possible in Scala before it matures enough?noncom
@noncom: for what it's worth, I tend to agree. However if the only solution (as per the thread I've linked) involved the compiler magically adding a constructor to all classes implementing the trait, I would be wary of subtle corner cases when further inheritance happens (similar to what used to happen with case class inheritance).Paolo Falabella

1 Answers

7
votes

Let's use our powerful tool called the REPL to understand what is going on:

scala>  trait Example[A<:Ordered[A]] { def contains(x:A):Boolean }
defined trait Example

scala>  class Example2[A<%Ordered[A]]( val a:A) { def isLower(otherA:A):Boolean = a< otherA }
defined class Example2

scala>  :javap Example
Compiled from "<console>"
public interface Example{
    public abstract boolean contains(scala.math.Ordered);
}


scala>  :javap Example2
Compiled from "<console>"
public class Example2 extends java.lang.Object implements scala.ScalaObject{
    public java.lang.Object a();
    public boolean isLower(java.lang.Object);
    public Example2(java.lang.Object, scala.Function1);
}

As you can see , the view bound becomes the second argument of the Example2 constructor. Since a trait does not have a constructor, clearly it is not possible to provide a view bound.

Why this has been possible in previous releases is to me a mistery (maybe an additional Function1 val was created inside the trait and filled by the compiler?)

Concerning your question about Scala evolution, it is mature and powerful. You can expect changes between major releases (2.8, 2.9, 2.10) but I would not consider scala not mature enough for this. There is, however, always space for improvement