Blog Posts

Understanding Scala's Type Classes

11 Jun 2012

Over the last year or so, I have found myself making more and more use of Scala's Type Class system to add flexibility to my code. This is especially evident in the MongoDB Scala Driver, http://github.com/mongodb/casbah, where the most recent work has been to simplify many features by migrating them to type classes.

During this work however, I've found during that many otherwise adroit Scala engineers seem befuddled or daunted by the Type Class. It does me no good to take advantage of clever features that my users don't understand, and many will benefit from introducing these concepts to their own code. So let's take a look at what type classes are, as well as how & why we can utilize them.

Wikipedia defines a Type Class as "... a type system construct that supports ad-hoc polymorphism. This is achieved by adding constraints to type variables in parametrically polymorphic types". Admittedly, a bit of a mouthful -- and not very helpful to those of us who are self taught and lack the benefit of a comprehensive academic Computer Science education (myself included). Surely, there must be a way to simplify this concept?

In evaluating these ideas, I've found it easiest to think of a Type Class (in Scala, at least) as a special kind of adapter, which can impart additional capabilities upon a given type or set of types. In Scala the Type Class is communicated through implicits, and imparts one, or both, of two behaviors. First, a Type Class can be to utilized to filter what types are valid for a given method call (which I detailed in this earlier post). Second, a Type Class can impart additional features and behaviors upon a type at method invocation time. This latter is much along the lines of an enhanced kind of composition, rather than the weaker inheritance which often plagues similar behaviors in a language like Java.

To better understand what I am describing, let's compare a few concepts around the creation and interaction of custom domain objects. I have several sets of tasks I have had to accomplish in Scala in the past -- and Scala solutions show some elegant Type Class oriented approaches which are rooted in the Standard Library. While this may seem a bit contrived, it is exactly the kind of problem through which I initially came to understand Type Classes –– and is thus an ideal lesson.

Read the rest of this entry »

Forcing Scala Compiler 'Nothing' Checks

31 May 2012

Since early in its history, Casbah has had a helper method called getAs[T], where T is "Some type you'd like to fetch a particular field as". Because of type erasure on the JVM, working with a Mongo Document can be annoying -- the representation in Scala is the equivalent of a Map[String, Any]. If we were to work with the Map[String, Any] in a standard mode, fetching a field balance which is a Double would require manual casting.

val doc: DBObject = MongoDBObject("foo" -> "bar", "balance" -> 2.5)

val balance = doc.get("balance") 

We have already hit another issue here -- in Scala, invoking get on a Map returns Option[T] (Where, in this case, T is of type Any). Which means casting has become more complex: to get a Double we also have to unwrap the Option[Any] first. A lazy man's approach might be something hairy like so:

balance.getOrElse(null).asInstanceOf[Double]

In the annals of history (when men were real men, and small furry creatures from Alpha Centauri were real small furry creatures from Alpha Centauri), the above became an annoyingly common pattern. A solution was needed - and so getAs[T] was born. The idea was not only to allow a shortcut to casting, but take care of the Option[T] wrapping for you as well. Invoking getAs[Double] will, in this case, return us an Option[Double].

But not everything is perfect in the land of getAs[T] -- if the type requested doesn't match the actual type, runtime failures occur. Worse, if the user fails to pass a type, the Scala compiler substitutes Nothing, which guarantees a runtime failure. Runtime failures are bad -- but fortunately, Miles Sabin & Jon-Anders Teigen came up with an awesome solution.

Read the rest of this entry »

Casbah 2.3.0-RC1 Released

29 May 2012

Today, I published the first Release Candidate of Casbah 2.3.0, available for SBT users as "org.mongodb" % "casbah" % "2.3.0-RC1". My release announcement to implicit.ly contains the details on all of the bugs fixed – I will also be posting another set of blog entries shortly outlining the specific improvements to the code and demoing fetaures.

It has been just about a year since the last major release of Casbah, which was version 2.1.5-1. A number of factors led to the delay in getting a major update out the door, for which I apologize. Amongst other things I have spent much of the last year since Casbah's prior release on the road doing training, consulting and evangelization of MongoDB to users around the globe; I had less time for code among all these things than I expected! Additionally, after releasing the 2.1.x series of Casbah I embarked on what quickly morphed from Casbah 2.2.0 to 3.0.0 – a major refactoring and cleanup of 2+ years of API cruft and "I'm Gonna Learn Me Some Scala!" detritus. In all the excitement to release a perfect release to end all releases, I did a poor job of making it easy to backport and maintain a compatibility series for 2.x users – a harsh lesson in the importance of creating small, bite sized git commits that can be cherry picked.

So What Happened to Casbah 3.0? And 2.2?

Casbah 2.2.x is dead – 3.0.x is certainly not! When the work following 2.1.x was begun, I had published a number of early snapshots as Casbah 2.2.0-SNAPSHOT. During this development cycle I found a lot of the aforementioned detritus such as overloaded methods (Casbah was begun as a Scala 2.7.x project and I never fully moved its core APIs over to use named and default arguments - some of these are corrected in Casbah 2.3.0 but in the interest of backwards compatibility with prior releases of 2.x, not completely). As I worked on coding improvements around these things the API drifted further and further away from compatibility and I chose to kill off the 2.2.x series, planning the next release of Casbah as 3.0.0. In addition to that, I intended Casbah 3.0.0 to coincide with MongoDB 2.2.0 which will have additional features such as the New Aggregation Framework. As MongoDB 2.2 hasn't been released yet, it became clear I needed to provide an updated Casbah release with many of the improvements but without many of the API breakages introduced in 3.0 - including a vastly improved build of the Casbah Query DSL which has stronger type safety and compiler checks thanks to the inimitable Jon-Anders Teigen.

Casbah 3.0 is still very much alive and in development, with 2.3.0 representing a backporting of many of the changes and improvements from 3.0. Because of the abandonment of the original 2.2 development series, I felt it was saner to kill 2.2.x dead and bring the backports into a 2.3.x series. You can, if you wish, think of this as Casbah 2.3 - The Search for Casbah 2.2 (The long rumored sequel to Spaceballs has been said to be called Spaceballs 3: The Search for Spaceballs 2).

I will continue to support and improve Casbah 2.3.x moving forward as well as completing Casbah 3.0 (still intended to coincide with the release of MongoDB 2.2). If you have any questions, please don't hesitate to contact me!

Later tonight or tomorrow I will post an entry or two detailing all of the wonderful changes in Casbah 2.3.0 and how to take advantage of them.