Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are type classes in Scala useful for?

Tags:

scala

implicit

As I understand from this blog post "type classes" in Scala is just a "pattern" implemented with traits and implicit adapters.

As the blog says if I have trait A and an adapter B -> A then I can invoke a function, which requires argument of type A, with an argument of type B without invoking this adapter explicitly.

I found it nice but not particularly useful. Could you give a use case/example, which shows what this feature is useful for ?

like image 646
Michael Avatar asked Mar 23 '11 16:03

Michael


People also ask

What are type classes used for?

A typeclass is a sort of interface that defines some behavior. If a type is a part of a typeclass, that means that it supports and implements the behavior the typeclass describes. A lot of people coming from OOP get confused by typeclasses because they think they are like classes in object oriented languages.

What does type do in Scala?

Type declaration is a Scala feature that enables us to declare our own types.

Does Scala have type classes?

Type classes are a powerful concept that is heavily used in functional programming. They were first introduced in Haskell to achieve ad-hoc polymorphism. They don't have native support in Scala, but we can use built-in features like traits and implicit classes to achieve them.

How does Scala determine types when they are not specified?

Non-value types capture properties of identifiers that are not values. For example, a type constructor does not directly specify a type of values. However, when a type constructor is applied to the correct type arguments, it yields a first-order type, which may be a value type.


1 Answers

One use case, as requested...

Imagine you have a list of things, could be integers, floating point numbers, matrices, strings, waveforms, etc. Given this list, you want to add the contents.

One way to do this would be to have some Addable trait that must be inherited by every single type that can be added together, or an implicit conversion to an Addable if dealing with objects from a third party library that you can't retrofit interfaces to.

This approach becomes quickly overwhelming when you also want to begin adding other such operations that can be done to a list of objects. It also doesn't work well if you need alternatives (for example; does adding two waveforms concatenate them, or overlay them?) The solution is ad-hoc polymorphism, where you can pick and chose behaviour to be retrofitted to existing types.

For the original problem then, you could implement an Addable type class:

trait Addable[T] {   def zero: T   def append(a: T, b: T): T } //yup, it's our friend the monoid, with a different name! 

You can then create implicit subclassed instances of this, corresponding to each type that you wish to make addable:

implicit object IntIsAddable extends Addable[Int] {   def zero = 0   def append(a: Int, b: Int) = a + b }  implicit object StringIsAddable extends Addable[String] {   def zero = ""   def append(a: String, b: String) = a + b }  //etc... 

The method to sum a list then becomes trivial to write...

def sum[T](xs: List[T])(implicit addable: Addable[T]) =   xs.FoldLeft(addable.zero)(addable.append)  //or the same thing, using context bounds:  def sum[T : Addable](xs: List[T]) = {   val addable = implicitly[Addable[T]]   xs.FoldLeft(addable.zero)(addable.append) } 

The beauty of this approach is that you can supply an alternative definition of some typeclass, either controlling the implicit you want in scope via imports, or by explicitly providing the otherwise implicit argument. So it becomes possible to provide different ways of adding waveforms, or to specify modulo arithmetic for integer addition. It's also fairly painless to add a type from some 3rd-party library to your typeclass.

Incidentally, this is exactly the approach taken by the 2.8 collections API. Though the sum method is defined on TraversableLike instead of on List, and the type class is Numeric (it also contains a few more operations than just zero and append)

like image 187
Kevin Wright Avatar answered Oct 02 '22 11:10

Kevin Wright