Identify and describe Scala's generic type constraints

S <: T means that S is a subtype of T. This is also called an upper type bound. Similarly, S >: T means that S is a supertype of T, a lower type bound.

S <% T is a view bound, and expresses that S must come equipped with a view that maps its values into values of type T.

It's confusing for me too, and I have a Masters in programming languages from Berkeley.


There are two different beasts here, but they're all know as "bounds" and not "constraints"...

First are the type bounds:

  • <: - uppper type bound
  • >: - lower type bound

These are essentially the same as super and extends in java, and will actually be encoded as such in the generated bytecode, which is good for interop :)

Then comes the syntactic sugar:

  • <% - view bound
  • : - context bound

These are NOT encoded in a way that Java could possibly understand (although they are represented in the scala signature, an annotation that scala adds to all classes to help the compiler, and which would ultimately be the base of an Scala reflection library)

Both of these are converted to implicit parameters:

def fn[A <% B](arg: A)  = ... //sugared
def fn[A](arg: A)(implicit ev: A => B) = ... //unsugared

def fn[A : Numeric](arg: A)  = ... //sugared
def fn[A](arg: A)(implicit ev: Numeric[A]) = ... //unsugared

For this reason, you can't combine your own implicits with either view bounds or context bounds, as Scala only permits one block labelled as implicit for any function or constructor.

If you do need to use your own implicits then you must first manually convert any such bounds to the unsugared version and add this to the implicit block.

Tags:

Generics

Scala