1

I want to write a function vaguely like:

def doubleit[A](a: A): A = {a + a}

But I want 'A' to mean any kind of Int, but not anything. Is there a way to give Scala a clue about what I want 'A' to mean?

def doubleit[A <: Int](a: A): A = {a + a}

is rejected by the compiler.

Salim Fadhley
  • 6,975
  • 14
  • 46
  • 83
  • 1
    possible duplicate of [How do I make a class generic for all Numeric Types?](http://stackoverflow.com/questions/4753629/how-do-i-make-a-class-generic-for-all-numeric-types) – Ben Reich Jan 22 '15 at 16:09
  • 1
    relevant blog: http://typelevel.org/blog/2013/07/07/generic-numeric-programming.html – Ben Reich Jan 22 '15 at 16:10
  • question has been edited. thanks for the suggestions. The numeric aspect is really a red-herring, I wanted to learn how to constrain generics. – Salim Fadhley Jan 22 '15 at 16:17

1 Answers1

6

In plain Scala you can use type class Integral:

scala> def doubleit[A : Integral](a: A): A = implicitly[Integral[A]].plus(a, a)
doubleit: [A](a: A)(implicit evidence$1: Integral[A])A

scala> doubleit(2)
res0: Int = 4

scala> doubleit(BigInt(4))
res1: scala.math.BigInt = 8

Another possible syntax:

def doubleit[A](a: A)(implicit ev: Integral[A]): A = ev.plus(a, a)

ev is a commonly used name for those implicit parameters.

It is also possible to use normal operations like +, -, etc. instead of plus and minus:

def doubleit[A](a: A)(implicit ev: Integral[A]): A = {
  import ev._
  a + a
}

Or as per suggestion by @KChaloux, import from Integral.Implicits beforehand:

import Integral.Implicits._
def doubleit[A : Integral](a: A): A = a + a

If you want the function to support not only integers, but also Doubles, BigDecimals, etc. you can use Numeric instead of Integral:

import Numeric.Implcits._
def doubleit[A : Numeric](a: A): A = a + a

Explanation:

Writing [A : Integral] makes the function receive an implicit parameter of type Integral[A]. The implicits for all basic integral types are already defined in Scala, so you can use it with Int or BigInt straightaway. It is also possible to define new Integral types by defining a new implicit variable of type Integral[NewIntegralType] and implementing all the necessary methods.

The call to implicitly[Integral[A]] returns this implicit instance of Integral[A] which has method plus for addition, and other methods for performing other operations on integrals.

Kolmar
  • 14,086
  • 1
  • 22
  • 25
  • 1
    It's also possible to `import Integral.Implicits._` and then just define your function as `doubleit[A : Integral](a: A) = a + a`. – KChaloux Jan 22 '15 at 21:08