In Scala you need to understand these magical symbols and terms:
- "type bounds", symbols: [T <: U] and [T >: U]
- "view bounds", symbol: [T <% U]
- "context bounds", symbol: [T : U]
Put bound terms into Google and it gives explanations.
As already said view bounds are deprecated and generalized by context bounds. View bounds (VB) are implicit function or constructor while context bound (CB) is an implicit value. VB says that it is required that a type can be viewed as another type. This "viewing" is implemented as a function which implicitly converts one type to another behind the scenes (done by compiler). Disadvantage is that this conversion is done on every call and has perf impacts. As well the original type identity is lost after conversion.
CB says that a type has required capabilities implemented in a separate instance (value). Pretty much like using a helper class in Java. This instance has to be implicitly available in a scope, either created or by importing and object which provides this instance. This value with implementation of required capabilities is as well called "evidence" as it proves that given type has implementation of required capabilities available. The advantage is that there is no conversion, every call is using the same instance with required capabilities implementation for a given type (there is one implementation and instance (object) for each type used). And type keeps its identity, it is not converted during the process. Hence we can work with Employee domain type without having to switch to RichEmployee type for serialization etc. I like that it is possible to read required capabilities from type signature - def do[T : C1 : C2 : C3]() = ??? where C1, C2, C3 refer to required capabilities which has to be implemented for the type T. It is similar when understanding requirements from input arguments - anyway each context bound is compiled into one input argument for default constructor - good to understand it when trying to do some magic with reflection as default constructor can have different signature than expected after compilation.
Context bound syntax [T : U] and view bound syntax [T <% U] can be replaced with currying with implicit value or function respectively:
Eqv.
def do[T <% U](x: T) = ???
def do[T](x: T)(implicit v: T => U) = ???
Eqv.
def do[T : U](x: T) = ??? // use implicitly[U[T]] to get the value with implementation
def do[T](x: T)(implicit ev: U[T]) = ??? // ev is the value (evidence) with implementation
It can be read as U is type which defines required capability. U[T] is an implementation of capability U for type T.
I hope it helps more that confuses you,
Petr