Identify and describe Scala's generic type constraints
Solution 1:
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.
Solution 2:
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.