No, it’s not the latest Coixet’s movie title. When we talk about cathegories like monoids, we tend to think they just remain on the edge as something merely experimental (even though purely functional) and there’s no direct application at the real world. Something similar happened when you learnt square roots at school and there was no proper moment to start using them at real life…

## The use case

This morning, ah *naïve* me, I tried to make this work:

type Passengers = Int type MaxCapacity = Passengers type Plane = (Passengers, MaxCapacity) val planes: List[Plane] = List(1 -> 1, 2 -> 3, 3 -> 3) val (totalPassengers, totalCapacity) = planes.sum // ERROR: Could not find implicit value // for parameter num: Numeric[(Int, Int)]

Ok, fair enough, Scala needs something, an evidence, for adding integer tuples.

Before we start fighting with the ‘evidence’, let’s try to make it work in a more mechanical way:

val sum = ((0,0) /: planes){ case ((totalPas,totalCap), (passengers, capacity)) => (totalPas + passengers, totalCap + capacity) }

Okay, it works. But it should be simpler, so let’s get back to the idea of `Numeric[N]`

evidence.

## Implementing `Numeric[N]`

We need a `Numeric[(A,B)]`

but before implementing it (it has a lot of abstract methods) let’s sweep under the rug all those methods we don’t really want to focus on in this example. For doing so, let’s create an intermediate layer that keeps all those method without an implementation (which doesn’t mean ‘abstract’):

trait LeanNumeric[T] extends Numeric[T] { override def fromInt(x: Int): T = ??? override def toInt(x: T): Int = ??? override def minus(x: T, y: T): T = ??? override def times(x: T, y: T): T = ??? override def negate(x: T): T = ??? override def toLong(x: T): Long = ??? override def toFloat(x: T): Float = ??? override def toDouble(x: T): Double = ??? override def compare(x: T, y: T): Int = ??? }

Let’s call this abomination LeanNumeric (it only contains the essentials to develop our example). And now, we can define the method that generates the evidence for any `Tuple2`

:

implicit def numeric[A, B]( implicit nA: Numeric[A], nB: Numeric[B]): Numeric[(A, B)] = { new LeanNumeric[(A, B)]{ override def zero = (nA.zero, nB.zero) override def plus(x: (A, B), y: (A, B)): (A, B) = { val (a1, b1) = x val (a2, b2) = y (nA.plus(a1, a2), nB.plus(b1, b2)) } } }

If we put the implicit into scope and we run again `planes.sum`

…boom! Magic.

## Num…oid

We don’t have to master category theory to realize that `Numeric[N]`

may be a thousand of things, but it satisfies at least two properties:

- The
**append**operation: The sum operation –*given n1 and n2 of type N, it return a new N element*. Only because of this feature(and the closure, associativity, commutative, …) we can consider it a**Semigroup**. - And additionally the
**zero**element

Seriously? Isn’t it obvious enough? My dear friends, monoid is back in town!

## Implementation with `scalaz.Monoid`

Having in mind that Numeric has (at least) these two properties, let’s re-implement the implicit by using scalaz Monoid. We first define the monoid for integers and the tuple monoid which requires a monoid for each type that compounds the tuple (easy peasy):

import scalaz._ implicit object IntMonoid extends Monoid[Int]{ override def zero: Int = 0 override def append(f1: Int, f2: => Int): Int = f1 + f2 } implicit def tupleMonoid[A,B]( implicit mA: Monoid[A], mB: Monoid[B]): Monoid[(A,B)] = { new Monoid[(A, B)] { override def zero: (A, B) = (mA.zero, mB.zero) override def append(f1: (A, B), f2: => (A, B)): (A, B) = { val (a1, b1) = f1 lazy val (a2, b2) = f2 (mA.append(a1,a2), mB.append(b1, b2)) } } }

So good so far, right?

After that, we implement the implicit that will provide a Numeric as long as there’s a Monoid for the type

implicit def numeric[T]( implicit m: Monoid[T]): Numeric[T] = { new LeanNumeric[T]{ override def zero = m.zero override def plus(x: T, y: T): T = m.append(x, y) } } planes.sum //(6,7)

And it’s awesomely easy to get abstract of whatever T means (a tuple? a dog? …). As long as it’s a monoid, you can define a LeanNumeric.

You can find here the gist.

See you in the next functional madness.

Peace out!