The power of Scala Type Classes
There are always several ways and styles of thinking to address problems. Type classes is another way of thinking and dealing with problems. For some problems, you might just use Pattern Matcher -- But if you have to add a type? Right, I could stick with good old OO since Scala is hybrid right? -- But what if you need to add one operator? Type Classes can help you out.
What Are Type Classes?
In order to have a type class you need to have:
1. A signature
2. All implementations for Supported Types(You can add more types later)
3. A function that requires a Type Classe
What are the Use Cases for Type Classes?
Type classes are great because of the make behavior more explicit and extendable. This "Behavior" more explicit happens because this will be checked at Compile Time. So you can extend and add more Behavior without re-compiling or be changing your previous code. That's why type classes are powerful.
What are the practical Use cases?
1. Business Rules / Domain Objects: Where you need to express different and customizable calculations. Doing this changes without breaking the client.
2. Pipelining: When you need to apply several different rules or a request.
3. Serialization/Deserialization: When you need express different parsing logic.
Sample Code
Now let's see some sample code. First code we will define some simple Math operations and we will use Implicits to apply automatic conversion for use.
So here we have a Trait called NumberLike witch is expecting a Class called T. Which could be any numeric type. Them we can a companion object with added support for 2 types Int and Double. This support is added via implicit objects called NumberLikeInt and NumberLikeDouble.
Finally, on the same object, we have 2 implicit conversions one to convert an Int into a NumberLikeInt and another to convert Doubles in NumberLikeDouble. Once we did the import on the main method we can use regular Int and Double add call our talk math methods.
The second sample is about behavior with different objects and the ability to add things later. So let's take a look at the following code.
Here we have 2 case classes: Person and Cat. We also have a Trait Can talk which expecting a Type T where T can talk. On AddOns companion object we have some default behavior implementations like PersonTalker and CatTalker witch allow Person and Cat to talk.
We also have an implicit class wrapper which gets a Type A and parameter X. This class provides the talk method where the CanTalk[A] will be implicit and will delegate to method talk passing the X argument.
Right after doing the write import we can call talk method on case class Person and Cat. We also can add new types so I defined a Dog after the fact.
Scala Type classes are really powerful and cool it allows to do really modular design and extend the design in a very clean and concise way. You can download the full source code and SBT project on my github here.
Cheers,
Diego Pacheco