A lot of what Scalaz does is made possible by using ad-hoc polymorphism, traits, and implicits. I’ll explain how this works by borrowing from Nick Partridge’s talk on Scalaz.

## Motivating Example

Let’s begin with a simple `sum`

function that adds together all the elements in a `List[Int]`

.

1 | scala> def sum(xs: List[Int]): Int = xs.foldLeft(0)( _ + _ ) |

The `sum`

function above works only with `List[Int]`

. If we want to sum together a `List[Double]`

, `List[Float]`

, or a `List[String]`

, we’d need a new implementation of `sum`

. Our goal is to make `sum`

function general so it would work with any of these.

## Step 1 - Monoid

The first step towards generalizing `sum`

is by using a monoid. A monoid is an algebraic structure with a single associative binary operation and an identity element.^{[1]}. Since we are working with a `List[Int]`

, let’s create an `IntMonoid`

.

1 | scala> object IntMonoid { |

`mempty`

is the identity or the zero value, and `mappend`

is the binary operation which produces another `Int`

i.e. another value in the set. These names come from Haskell^{[2]}.

## Step 2 - Generalizing the Monoid

Next, we’ll generalize the monoid by creating a `Monoid[A]`

so that `IntMonoid`

is just a monoid on `Int`

.

1 | scala> trait Monoid[A] { |

What we’ve done is create a general-purpose `sum`

function whose working depends upon which monoid is passed to it. Now we can very easily sum a `List[String]`

or a `List[Double]`

by adding a corresponding monoid.

## Step 3 - Make the Monoid Implicit

Next, we’ll make the monoid an implicit parameter to our `sum`

function. We’ll also package our `IntMonoid`

into a `Monoid`

companion object and make it implicit. The reason for doing this is how Scala compiler resolves implicit values; it’ll look for implicit values in its scope. So, we bring `IntMonoid`

within scope by importing from the `Monoid`

companion object.

1 | scala> trait Monoid[A] { |

So, what we’ve done is create a general-purpose `sum`

function that works as long as there is a corresponding implicit monoid within scope. This is made possible by using ad-hoc polymorphism. I’ll cover ad-hoc polymorphism briefly in this post and defer providing a detailed explanation for a later post.

## Ad-hoc Polymorphism

Ad-hoc polymorphism is a type of polymorphism in which polymorphic functions are invoked depending on the different argument types. One way to implement ad-hoc polymorphism that we already know about is function overloading where a different “version” of the function is invoked depending on the type of arguments. This is what we’ve done in the post where there is only a single function but an implementation is provided for different types. In other words, `sum`

only knows how to be invoked but the behavior is provided by monoids. Another way to implement ad-hoc polymorphism is coercion where the argument is converted into a type which the function expects.

So, by using ad-hoc polymorphism, Scalaz is able to provide general-purpose functions over existing types. Ad-hoc polymorphism is flexible in the sense that it lets you extend even those classes for which you do not have access to the source code i.e. classes from other libraries, etc.