In Programming in Scala there is an example Rational class which

begins

class Rational(n: Int, d: Int) {

require(d != 0)

private val g = gcd(n.abs, d.abs)

val numer = n / g

val denom = d / g

…

I just want to verify that g sticks around for the life of the

object so

that 3 values are stored instead of just 2. If space was more

important

than time, this would be more efficient:

That’s correct, `g`

would occupy the space of one `Int`

.

You could also write

```
class Rational(n: Int, d: Int) {
require(d != 0)
val (numer, denom) = {
val g = gcd(n.abs, d.abs)
(n/g, g/d)
}
}
```

although it might perform slightly worse due to the temporary

construction of a tuple. Or use a companion object

```
object Rational {
def apply(n: Int, d: Int): Rational = {
require(d != 0)
val g = gcd(n.abs, d.abs)
new Rational(n/g, g/d)
}
}
class Rational private(val numer: Int, val denom: Int)
```

Probably this would be the best form.

It seems like a templated Rational[T] would be effective,

but not just any T has an abs function (among others). I can’t figure

out how to use Integral or anything like it in the template. Can someone

show a way to have

There are so-called type classes for numeric operations: Numeric

(addition, multiplication), Fractional (adds division), Integral (adds

modulus). You need Integral because gcd requires modulus.

There are default instances for Int, Long and others

```
implicitly[Integral[Long]] // -> scala.math.Numeric.LongIsIntegral
```

(http://www.scala-lang.org/api/current/scala/math/Numeric$.html)

These have the necessary math operations, e.g.

```
scala.math.Numeric.LongIsIntegral.rem(10L, 6L) // 4
```

If you import the members of such an instance of Integral, you can use

’operators’ almost as before (because it provides extension methods

through `mkNumericOps`

). So instead of

```
def gcd[A](a: A, b: A)(implicit num: Integral[A]): A = {
if (b == num.zero) a else gcd(b, num.rem(a, b))
}
```

you can write

```
def gcd[A](a: A, b: A)(implicit num: Integral[A]): A = {
import num._
if (b == zero) a else gcd(b, a % b)
}
```

Then the whole class could be written

```
object Rational {
def apply[A](n: A, d: A)(implicit num: Integral[A]): Rational[A] = {
import num._
require (d != zero)
val g = gcd(n.abs, d.abs)
new Rational(n / g, d / g)
}
private def gcd[A](a: A, b: A)(implicit num: Integral[A]): A = {
import num._
if (b == zero) a else gcd(b, a % b)
}
}
class Rational[A] private (val numer: A, val denom: A)(implicit num:
Integral[A]) {
import num._
override def toString = s"$numer/$denom"
def + (that: Rational[A]): Rational[A] =
Rational(numer * that.denom + that.numer * denom,
denom * that.denom)
}
```

Test:

```
Rational(4L, 8L) + Rational(5L, 9L) // 19/18
```

best, .h.h.