The last year I’ve learned Scala to the point of literacy. In the course of doing so, I also acquired some hands-on understanding of functional programming patterns. In this post I’m going to attempt to define some common terms that get thrown around by Scala people with the hope of providing a sort of glossary.
If you’ve worked with a language with generics support like Java, you’re surely familiar with common generic types like List. List itself is not a type. We can’t actually refer to a List in Java. Rather, we have to a refer to concretization like List<Integer> or List<String>. We can think of List itself as a type which, given some parameter (which is a type itself), itself produces a type.
In Scala this is called a type class or a type constructor. Back to our Java example, try to think of List as a special function that knows how to build a type given another type.
The term “monoid” sounds complicated, but without even getting into the abstract algebra behind it, we can define it in simple practical terms.
Simply put, a monoid is a type that can be combined. A nicer name might be addable. To define a monoid, we need two things:
– The definition of “zero” for this type. (E.g., the number 0, an empty string, an empty list.)
– An operator that defines how to combine two instances of the type.
“Combining” in this sense can mean anything – adding, subtracting, concatenating strings – as long as it is associative.
Another complicated sounding name for something powerful and expressive, monads are the cornerstone of functional programming. The monad is a design pattern that allows purely functional programs to be written in an imperative style.
I like to think of monads as mappables. Whereas the monoid defines a thing that can be added, the monad defines a thing that can be transformed. Monads are useful for modeling side-effects in a purely functional way.
List is a simple example of a monad. Given a List<String> (or List[String] in Scala), we could define a function which, given a String, produces another String. This might do something like transform some text into its uppercase form. Or we could transform the String to an Integer, e.g. by finding the length of the string buffer.
Note that the transformation is defined in terms of the contents of the List, but the transformation operation occurs on the List itself. In other words, our transforming function is:
String => Integer
But the transformation is:
List[String] => List[Integer]
More generally, we write this as:
F[A] => F[B]
A => B
The transformation operation is called map in functional terminology, and F in the above example is our monad. Fancy name for a powerful design pattern that allows us to generically compose statically typed programs with no sucky side-effects.