49

I've seen <:, >:, <%, etc. Can someone give (or locate) a good description of these? What are the possible constraints, what do they do, and what's an example of when to use them?

Leif Wickland
  • 3,693
  • 26
  • 43
waterlooalex
  • 13,642
  • 16
  • 78
  • 99
  • 1
    I like this interpretation http://stackoverflow.com/questions/2982276/what-is-a-context-bound-in-scala/2983376#2983376 – huynhjl Feb 02 '11 at 03:06
  • possible duplicate of [What are Scala context and view bounds?](http://stackoverflow.com/questions/4465948/what-are-scala-context-and-view-bounds) – Suma Apr 29 '15 at 12:55
  • 1
    See [O'Reilly's _Programming Scala_](http://ofps.oreilly.com/titles/9780596155957/index.html). Start at [Type Bounds](http://ofps.oreilly.com/titles/9780596155957/ScalasTypeSystem.html#TypeBounds). I think this does a good job of explaining Type and View bounds. – Dan_Chamberlain Feb 02 '11 at 02:07

2 Answers2

70

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.

Raph Levien
  • 5,088
  • 25
  • 24
55

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.

Ben Reich
  • 16,222
  • 2
  • 38
  • 59
Kevin Wright
  • 49,540
  • 9
  • 105
  • 155