Software engineering as a discipline has a large number of different subjects to learn on the road to mastery. Typeclasses is one of those which like data structures and algorithms, there are certain expectations which once learnt can help solve problems in different and more effective ways.

Typeclasses are interesting as they are a common set of API across the various functional programming languages and each have at least one law which they must implement for each type. Like the hashcode() method in JVM languages, there are certain criteria they must adhere to.

Here are a few examples of typeclasses to get you started


For a type A you can combine it with another of the same type to create another A:

String.semigroup().run { "1".combine("2") } // 12


Similar to Semigroup but also adds an empty result. This is very similar to Java 8’s Optional type.

String.monoid().run { "1".combine("2") } // "12"
String.monoid().run { listOf("1", "@", "3").combineAll() } // "1@3"
String.monoid().run { empty() } // ""


Provides the map ability which will either return a result or nothing

Option(1).map { it * 2 } // Some(2)
empty<Int>().map { it * 2 } // None


Similar to Functor but instead of map it provides flatMap which will return a new Monad instead of the unwrapped value. This is very useful for chaining together logic to a final result or nothing result.

Option(1).flatMap { Option(it * 2) } // Some(2)
empty<Int>().flatMap { Option(it * 2) } // None

  .flatMap { Option(it * 2) } // Some(2)
  .map { it + 2 } // 4


MonadError can then be used in conjunction with Monad to handle failures. This uses the Either type from Arrow which is a functional way of handling errors besides using try ... catch blocks. fold is a way of handling Either by providing handlers for the ‘left case’ and ‘right case’.

IO {
  1 / 0  
                { "Failed: ${it.message}" },
                { "Success!: $it" }
        ) // "Failed: / by zero