The first time I heard about cats library was in a video by the author @d6 in late 2014, quite interesting, I immediately jumped to the website to learn more, the first thing that scared me away was the logo (4 cats with 5 directional arrows), I told myself - this library is not for mortals :(
I had no option than to hold on for a while, perhaps things will get clearer in the future, I followed the advise of @kaffeecoder in his blog series the-neophytes-guide-to-scala
“More often than not, a good way to really get comfortable with a new language and its whole ecosystem of libraries is to use it for creating something useful”
A started out by building a GPS aggregation application with playframework, and surprise surprise I needed to do some very basic stuffs like
- Sum up Scala list of Options without multiple mappings.
- Manipulating value inside a future of options.
- Concatenating future of future.
- and many more……….
These were obviously not very friendly to do in standard Scala, but fortunately the tutorial on herding cats by @eed3si9n gave me all I needed to learn cats - that cats library was ONLY a library that followed the category theory principles and I needed not to study category theory before I can use it.
This greatly helped me to solve the 3 concerns I mentioned above and dive more into the type-level programming.
Apply, Semigroup, Applicative, Functor, Monoid, Monad — these buzzy words scares object oriented programmers with no background in functional programming(like me). But believe me, they are simply type classes that follows some specific laws.
Let start with Functors
Functors — is a “type class” that have one key function called “map” which is meant for manipulating data types like List[Int] , Option[String] and Futures[Int]( data types of this natural are generically denoted as F[A])
def map[A, B](fa: F[A])(f: A => B): F[B]
explanation of the functor map function.
(fa : F[A]) — a data-type that take only one data-type e.g List, Future , Options(f: A => B ) — a function that transform a type A to a type B e.g function that takes a string and return an Int. F[B] — the final return type of the Functor's map function e.g if our "fa" variable is a List[String] and our "f" function is String => Int , then our map function return type will be a List[Int]
To get started with SBT, simply add the following to your build.sbt file:
libraryDependencies += "org.typelevel" %% "cats" % "0.7.2"
import cats to your REPL
scala> import cats._, cats.instances.all._
import cats.instances.all._scala> val len: String => Int = _.length
len: String => Int = <function1>scala> Functor[List].map(List("scala", "cats")) (len)
res0: List[Int] = List(5,4)
Using Either as a Functor
The standard Either type in Scala does not have a “map” function, however, the cats library defines a Functor instance for it.
scala> import cats.syntax.functor._
import cats.syntax.functor._scala> val r: Either[String, Int] = Right(100)
r: Either[String,Int] = Right(100)scala> r.map( x => x + 1 )
res1: Either[String,Int] = Right(101)
One beautiful function inside the cats Functor’s type class I liked some much is the “fproduct” which pairs a value with the result of applying a function to that value.
scala> val len: String => Int = _.length
len: String => Int = <function1>scala> List(“scala”, “cats”).fproduct(len)
res3: List[(String, Int)] = List((scala,5), (cats,4))
to make is more readable and useful the result can be converted to a Map collection ;) using toMap
res4: scala.collection.immutable.Map[String,Int] = Map(scala -> 5, cats -> 4)
There are also more cool functions in the cats functor type class that you can try out e.g lift , compose , as.
If you like this writeup, click the💚 below so more people can see it here on Medium.