A year ago I started my journey in Scala. It’s just a nicer Java they said. But there is this camp of people who wanted to use Scala for functional programming. In order to truly understand that idea, one must understand its philosophy.
Delay as much as possible
The ideal program in a functional paradigm is to describe what should happen and then only executing it at the very end.
Composition is key
Suppose we have a function f: A => B
and another g: B => C
, high school maths reminds us that we can compose them to get a function g o f : A => C
(ignoring the domain constraints). Hence rather than writing
def lengthOfEvenNumber(a: List[Int]): Int = {
val x = a.filter(_ % 2 == 0)
val y = x.size
y
}
It is preferable to write
def length of EvenNumberF(a: List[Int]): Int = filter(_ % 2 == 0) >> (_.size)
Note: » is just the syntax for flatmap.
How far can one push composition?
What if f: A => M[B]
and g: B => M[C]
where M is some “container” (think of M as a List for example). Can we still compose f
and g
in some manner?
That’s where Kleisli
comes in. It is a datastructure that’s “describing” such functions the same way as IO
is a datastructure that “describes” the unsafe work to be done [to the real world].
Think of Kleisli[M ,A, B]
as representing a function of type A => M[B]
By wrapping f
and g
with Kleisli
, we can now do composition as follows:
val p = Kleisli[M, A, B] (f)
val q = Kleisli[M, B, C] (g)
val r: Kleisli[M, A, C] = p >> q
What are the trade offs here?
On the plus side, we are now able to compose functions that returns a container.
However, this comes at a cost of learning the semantics and motivation of such datastructures. It took me several occasions to grasp this idea and the myraid of academic topic in the domain of category theory does not help keep the research on track.