Thursday, November 30, 2017

Type Classes in Scala



Type classes are useful in providing an interface implementation types without the types implementing the interface themselves i.e. the interface implementation is independent of the type source code.

Hence, type classes can be used to extend the functionality of even those classes for which the source code is not available.

Examples:
Numeric[T] and Ordering[T] are examples of type classes in the Scala library.

Numeric[T] provides a unified interface for all numeric types in Scala even though the numeric types do not share a common super type.

Ordering[T] provides an interface for implementing ordering strategy/logic for sorting a type.

Note
Type classes are not first order citizens in Scala. They are instead implemented via a combination of the following:
  1. traits - for defining the interface
  2. implicit objects - for defining the concrete implementation of the defined trait
  3. parameterised curried method with an implicit parameter list - for restricting the type variable T to the types that have implementations of the defined trait
 Example:

Below is an example of a trait 'MyStringLike' that has a method 'len' which returns the length of a type A value.

The companion object implements MyStringLike[A] for type = Int


trait MyStringLike[A] {
 def len(x : A): Int
}

object MyStringLike {
  implicit object MyStringLikeInt extends MyStringLike[Int] {
    def len(x: Int) = x.toString.length
  }
}


The following are 2 different implementations of the length method which makes use of type class 'MyStringLike' to return the length of some type A for which an implementation of MyStringLike[A] exists.



import MyStringLike._

def mylen[T](x: T)(implicit v: MyStringLike[T]) = v.len(x)
mylen: [T](x: T)(implicit v: MyStringLike[T])Int

def mylen2[T : MyStringLike](x: T) = implicitly[MyStringLike[T]].len(x)
mylen2: [T](x: T)(implicit evidence$1: MyStringLike[T])Int


The 2nd variant where the implicit parameter list is absent is referred to as the context bound notation. Here the type variable T is restricted those types for which MyStringLike[T] implementation exists.


References

[1] https://www.cakesolutions.net/teamblogs/demystifying-implicits-and-typeclasses-in-scala
[2] http://blog.muhuk.com/2013/09/29/unified_support_for_numbers_in_scala.html#.Wh988rT1VR1
[3] http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html

No comments: