If you want to use only the standard scala library, see Numeric[T] . In your case, since you want to do non-integer division, you will need to use the Fractional[T] Numeric subclass.
Here's what the code would look like using standard scala style classes. Note that Fractional continues from Ordered . This is convenient in this case, but it is also not mathematically general. For instance. you cannot define Fractional[T] for Complex because it is not ordered.
def bucketiseScala[T: Fractional](buckets: Seq[T], candidate: T): T = { // so we can use integral operators such as + and / import Fractional.Implicits._ // so we can use ordering operators such as <. We do have a Ordering[T] // typeclass instance because Fractional extends Ordered import Ordering.Implicits._ // integral does not provide a simple way to create an integral from an // integer, so this ugly hack val two = (implicitly[Fractional[T]].one + implicitly[Fractional[T]].one) buckets.foldLeft(buckets.head) { (x, y) => val midPoint = (x + y) / two if (candidate < midPoint) x else y } }
However, for serious general computing, I would suggest taking a look at spire . It provides a much more complex hierarchy of number types. Spire typeclasses are also specialized and therefore often as fast as working directly with primitives.
Here's how to use the spire example:
// imports all operator syntax as well as standard typeclass instances import spire.implicits._ // we need to provide Order explicitly, since not all fields have an order. // Eg you can define a Field[Complex] even though complex numbers do not // have an order. def bucketiseSpire[T: Field: Order](buckets: Seq[T], candidate: T): T = { // spire provides a way to get the typeclass instance using the type // (standard practice in all libraries that use typeclasses extensively) // the line below is equivalent to implicitly[Field[T]].fromInt(2) // it also provides a simple way to convert from an integer // operators are all enabled using the spire.implicits._ import val two = Field[T].fromInt(2) buckets.foldLeft(buckets.head) { (x, y) => val midPoint = (x + y) / two if (candidate < midPoint) x else y } }
Spire even provides automatic conversion from integers to T if Field[T] exists, so you can even write an example like this (almost identical to the non-universal version). However, I think the above example is easier to understand.
// this is how it would look when using all advanced features of spire def bucketiseSpireShort[T: Field: Order](buckets: Seq[T], candidate: T): T = { buckets.foldLeft(buckets.head) { (x, y) => val midPoint = (x + y) / 2 if (candidate < midPoint) x else y } }
Update: The spire is very powerful and general, but can also be somewhat confusing for beginners. Especially when something is not working. Here is a great blog post explaining the basic approach and some of the problems.