Why StackMob uses Scalaz with Scala

Posted By Douglas Rapp on Wednesday, November 2nd, 2011

At StackMob we spend a lot of time working hard to deliver the most solid, scalable product available to build, deploy and scale your mobile applications. A lot of this work goes on behind-the-scenes everyday and we wanted to share with everybody the awesome work we are doing here. StackMob is primarily a Scala shop and more and more we have been embracing many of the functional programming paradigms that come along with Scala. One way we have done so is by starting to make heavy use of a library of “Typeclasses and Purely Functional Datastructures” called Scalaz.

We’ve begun to see huge benefits as we continue to write more and more in the functional style. Some of the biggest of those are more reusable, consice code that gives us the ability to iterate on new features much quicker than before and having an easier time tracking down, reasoning about and isolating error conditions. In this post we will talk about the theory behind typeclasses, their benefits, and how they are made available via Scalaz. The examples below assume some familiarity with Scala and an interest in Functional Programming. The content here are excerpts from a tutorial series on Scalaz that some of our engineers have begun working on.

So let’s talk about Scalaz!

What is Scalaz?

Scalaz’s Google Code page says it is a library of “Type Classes and Pure Functional Data Structures.” It also uses a pattern known in Scala as “Pimp My Library.” What does this mean? In this post we will talk about all of that. Knowing what they are isn’t the only thing that is interesting, however. It’s how we use them and why they make our code better that we really want to know. We will only begin to scratch the surface of the “hows” & the “whys” in this part. First, we must go over the “whats”.

Typeclasses == Classes of Types

Typeclasses are classes of types. I can hear my 1st english teacher telling me, “you can’t use the word you’re defining in the definition, young man.” Correct he is — and was, although I can’t quite remember the word.

So let’s get a better defintion.

Typeclasses define a finite set of behaviors on a possibly infinite set of types. 

Let’s pick that apart. We have two sets of things in play here. The first is a finite set of behaviors (read functions, or if you prefer methods). The second is a possibly infinite set of types. A possibly infinite set of types, that needs some more explanation. Infinite doesn’t always mean all of the possible Scala types we could ever write. We might be talking about them, but we could also be talking about all types we could write that are parameterized by one, or even two types. In functional programming and Scalaz we are often talking about types that meet some mathematical property, often from a branch of Mathematics called Category Theory.1

Typeclasses in Scala

Typeclasses are like interfaces on steroids. Hmm, That sounds familiar…quick grab your nearest Scala book, its probably in the chapter about traits! Traits, in the purely OOP sense allow for multiple inheritance. For our purposes they let us define not only abstract behavior but also concrete behavior, typically built on-top of the abstract stuff (or maybe not). Scala, also, has a really powerful type system that you can use to control how traits are used as well as their behaviors. Combine these two together and you can start writing Scala typeclasses. But wait, I said abstract behavior. That sounds like inheritance. Functional programming doesn’t mean we have to throw the object-oriented baby out with the bath water. We need to implement that abstract behavior somewhere, its how we get those finite sets of types for our typeclasses, and in Scala we use inheritance and concrete classes or objects to do it.

Traits can be mixed into any class hierarchy and are a great way to help you think about typeclasses. Typeclasses describe functionality that can be performed on a bunch of seemingly unrelated types as long as those types satisfy certain conditions.

Why Typeclasses?

In classic Object Oriented Programming we use a class hierarchy to organize related domain objects and functionality shared between them. Any gives us all of the functionality we can use on any Scala object. For the most part it makes sense, but in many cases it doesn’t. A common pitfall of OOP is having to “fudge” the definition of a method so that we can move it up the class hierarchy or “dirtying the class hierarchy.” You begin to litter superclasses with methods that must be shared across subclasses but as a result some subclasses that “dont really” fit with the behavior get it anyway.2 This leads to more edge case handling in the method and even causes clients of the method to do more edge case handling as well. The equality operator (==) is a great example of this, especially in Scala. At first, it seems obvious that we can compare any two things for equality. Why shouldn’t I be able to ask if "1" == 1? You can in Scala if you want, but more often that not you will ask it accidentally and you will be surprised when your code doesn’t run the expected branch of the if expression because comparing two instances of different types in Scala will always return false.

scala> 1 == "1"
res1: Boolean = false

The truth is its not Scala’s fault that == works this way. Its a product of the JVM it runs on. Scala does its best to tell you at compile time that you’re most likely doing something you didn’t mean to.

Warning: comparing values of types Int and java.lang.String using `==’ will always yield false 1 == “1″ ^

The warning is a nice helper but typesafe compilers are even more helpful when they give us compiler errors when we are about to do something wrong. The problem is we can’t make == typesafe because it is defined on Any. 3 Many times in our own classes we handle this with something like

class A {
    …
    def equals(o: Any) = o match {
       case oa: A => // real equality checking here
       case _ => false
    }
    …
}

This is where typeclasses make our code better. We can avoid this repetition and code smell. Instead we can define a typeclass for all types that can be compared to others of the same type for equality.

A Scalaz Example – The Equal Typeclass

The Equal typeclass encompasses all types for which any two instances of that type can be compared for equality. In Scalaz, it is defined as

// https://github.com/scalaz/scalaz/blob/master/core/src/main/scala/scalaz/Equal.scala
trait Equal[-A] {
    def equal(a1: A, a2: A): Boolean
}

Like we said above, Scala traits help us to define typeclasses. Before we talk about the equal function lets look at the definition of the trait: trait Equal[-A]. The definition leverages more than traits but also the Scala type system, like we said it would. Equal is parameterized by a single type. We use the type variable A to represent this type. In type classes it is always the case that our traits will be parameterized by some number of types. The trait lets us group similar behavior (the finite set) and the type parameters let us talk about the set of types the behaviors apply too.

Equal allows us to do type-safe equality checks using ===. Before we can understand how this new operator works with our code we need to understand a common pattern to extend types in Scala, “Pimp My Library”.

Pimp my Ride

The Pimp my Library pattern allows you to extend existing classes with new functionality without changing their original definition. We call these extensions pimps. If you’ve written Ruby this may sound similar to Monkey Patching and it is. The difference is its typesafe and you get all that compile time goodness! Scala itself uses this pattern everywhere, its how your Java strings have super powers and how you can give them to your Java collections as well (by importing scala.collection.JavaConversions._).

The key to the pattern is another feature of Scala: implicits. Using implicits you can convert one type to another without having to explicitly say so in your code. In our case we want to convert our type (or class) to a wrapper that provides the additional functionality. Maybe you want to add the method fortyTwo to any instance of List. Lets do that. The first step is to define a class that is paramterized by a List (you can also use a trait, remember the key here is implicits) and define the fortyTwo method.

scala> class ListFortyTwoW[T](xs: List[T]) {
       | def fortyTwo: T = xs(41)
       | }
defined class ListFortyTwoW

ListFortyTwoW could be instantiated directly and then we can call fortyTwo on the list we passed into it,

scala> (new ListFortyTwoW(Nil)).fortyTwo
java.lang.IndexOutOfBoundsException: 41

but thats verbose, nasty and most importantly not very interesting. What would be interesting is being able to call List(1, 2, 3).fortyTwo. That’s not something given to us by the Scala Standard Library. When you call a method that is not defined for a type Scala will look in scope for an implicit function that converts the instance to a type that does. We need one of those, and as you might have guessed it’s pretty easy to define.

scala> implicit def listToFortyTwoW[T](xs: List[T]) = new ListFortyTwoW[T](xs)
listToFortyTwoW: [T](xs: List[T])ListFortyTwoW[T]

With the implicit in scope we can now call our method on a list.

scala> List(1, 2, 3).fortyTwo
java.lang.IndexOutOfBoundsException: 41

We have just extended Scala lists! Scalaz uses this pattern to provide a succinct way of using typeclasses.

Identity, MA, MAB

The core Pimps of Scalaz are Identity, MA and MAB. At first these names may seem somewhat non-sensical but once you know what they do it makes a bit more sense. Identity applies to all Scala types, MA to all types M parameterized by one type A and MAB to all types M parameterized by types A and B (remember these are not concrete types but type variables).

It may also sound like these pimps are typeclasses but this is not the case. It is true that each of them do define some behavior common to all types but they are just highly general pimps (unlike the one we defined above that only works on lists). Remember, the pimps give us a convenient way to do this. In fact they include behavior from several typeclasses using implicits. Earlier I said typeclasses are defined using traits and the type system. This does not mean all traits that are polymorphic are typeclasses. Some of what is in these pimps are also convenience methods or notation. For example, |> is defined in Identity as,

// https://github.com/scalaz/scalaz/blob/master/core/src/main/scala/scalaz/Identity.scala
def |>[B](f: A => B): B = f(value)

This function takes a function from A => B and calls it on the instance of A that Identity wraps, returning the resulting B.

Back to the Equal Typeclass

Let’s jump back to the Equal typeclass and see how Scalaz gives us the convenient === operator via Identity.

// https://github.com/scalaz/scalaz/blob/master/core/src/main/scala/scalaz/Identity.scala
def ===(a: A)(implicit e: Equal[A]): Boolean = e equal (value, a)

The defintion of === has two argument lists, the second of which is implicit. Scala allows us to do this so that we can define more convenient ways to use functions. In the case of this defintion we can call === on any type A (A will first be implicitly converted to an Identity[A]) for any A which has a corresponding Equal[A] defined. This only works if both the implicit conversion from A to Identity[A] and an implicit Equal[A] are in scope. This is why the methods defined in Identity, MA and MAB don’t always apply to all of the types the pimps encompass. If we don’t have a Equal[A] for our A then it is not a member of the Equal typeclass and we can’t use the === behavior on it.

With all of that in mind we have a pretty clear picture of what Scala typeclasses look like. They are represented using polymorphic traits and the scala type system. We provide convenient access to the behaviors they define on certain types using pimps and implicits. They also have significant benefits. We’ve shown how typeclasses give us more modularity as well as type-safety. They can also prevent unnecessary conversions between types. In Scala we can map over a Java Collection by first boxing it in a Scala Iterable type. Using a the Functor4 typeclass we can define map in terms of the Java Collection API and avoid what may be an expensive conversion. These are just a few of the benefits of using typeclasses.

1 Category theory will not be covered in this post.

2 Of course, the GOF give us lots of patterns to make our OOP code better but they don’t help us clean up everything.

3 How == is defined is actually a bit more complicated than just that one method but thats a topic that will be covered in detail in your Scala book.

4 Functor is the first of a series of detailed and complex typeclasses that deserve a separate post and will not be covered here

Get Access to the StackMob Private Beta and check out StackMob for yourself.

Already have a Beta Invite? Login Here

Comments

comments