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

Semigroup

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

Monoid

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() } // ""

Functor

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

Monad

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

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

MonadError

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  
}.attempt()
        .unsafeRunSync()
        .fold(
                { "Failed: ${it.message}" },
                { "Success!: $it" }
        ) // "Failed: / by zero