One of the new features of Scala 2.8 are context bounds. What is a context bound and where is it useful?
Of course I searched first (and found for example this) but I couldn't find any really clear and detailed information.
One of the new features of Scala 2.8 are context bounds. What is a context bound and where is it useful?
Of course I searched first (and found for example this) but I couldn't find any really clear and detailed information.
Did you find this article? It covers the new context bound feature, within the context of array improvements.
Generally, a type parameter with a context bound is of the form
[T: Bound]
; it is expanded to plain type parameterT
together with an implicit parameter of typeBound[T]
.Consider the method
tabulate
which forms an array from the results of applying a given function f on a range of numbers from 0 until a given length. Up to Scala 2.7, tabulate could be written as follows:In Scala 2.8 this is no longer possible, because runtime information is necessary to create the right representation of
Array[T]
. One needs to provide this information by passing aClassManifest[T]
into the method as an implicit parameter:As a shorthand form, a context bound can be used on the type parameter
T
instead, giving:(This is a parenthetical note. Read and understand the other answers first.)
Context Bounds actually generalize View Bounds.
So, given this code expressed with a View Bound:
This could also be expressed with a Context Bound, with the help of a type alias representing functions from type
F
to typeT
.A context bound must be used with a type constructor of kind
* => *
. However the type constructorFunction1
is of kind(*, *) => *
. The use of the type alias partially applies second type parameter with the typeString
, yielding a type constructor of the correct kind for use as a context bound.There is a proposal to allow you to directly express partially applied types in Scala, without the use of the type alias inside a trait. You could then write:
This is another parenthetical note.
As Ben pointed out, a context bound represents a "has-a" constraint between a type parameter and a type class. Put another way, it represents a constraint that an implicit value of a particular type class exists.
When utilizing a context bound, one often needs to surface that implicit value. For example, given the constraint
T : Ordering
, one will often need the instance ofOrdering[T]
that satisfies the constraint. As demonstrated here, it's possible to access the implicit value by using theimplicitly
method or a slightly more helpfulcontext
method:or
Robert's answer covers the techinal details of Context Bounds. I'll give you my interpretation of their meaning.
In Scala a View Bound (
A <% B
) captures the concept of 'can be seen as' (whereas an upper bound<:
captures the concept of 'is a'). A context bound (A : C
) says 'has a' about a type. You can read the examples about manifests as "T
has aManifest
". The example you linked to aboutOrdered
vsOrdering
illustrates the difference. A methodsays that the parameter can be seen as an
Ordered
. Compare withwhich says that the parameter has an associated
Ordering
.In terms of use, it took a while for conventions to be established, but context bounds are preferred over view bounds (view bounds are now deprecated). One suggestion is that a context bound is preferred when you need to transfer an implicit definition from one scope to another without needing to refer to it directly (this is certainly the case for the
ClassManifest
used to create an array).Another way of thinking about view bounds and context bounds is that the first transfers implicit conversions from the caller's scope. The second transfers implicit objects from the caller's scope.