Functional Programming: So what is for-comprehension and Monad in Scala? Part 2:

Part 1 @

https://medium.com/@mageswaran1989/functional-programming-so-what-is-for-comprehension-and-monad-in-scala-eed22d52e3f7

In last post we saw what is a monad or what makes a monad in Scala.

Code @ https://github.com/dhiraa/medium/tree/master/for-comprehension

In short a class/container which had map() and flatmap() implemented can informally be called as a Monad, which then can be used easily inside for expresssion.

In this post we will see what really happens inside the for expression and how the function calls are chained.

When using multiple generators in `for expression`, it is desugared as chain of flatmap calls followed by map call with the yield expression as the map’s lambda function body. For simplicity we have used Option as our monad (though there is no definition of monad as such in Scala)

Following is the complete example to chain multiple functions with Higher Order Functions (H.O.F) and with for expression. While latter output will be discussed in detail.

Going from H.O.F to `for expression`, you will see a class called DebuggleWrapper, which implements two needed functions map() and flatmap() along with some debug prints. The only difference we see between map and flatmap is with the in argument function signature.

Note: Inside the map() and flatmap() we use class variable “value”

When compiled following code

it generates

with some clean up we have

When we run this we get following output:

Disclaimer:

For better understanding, requesting you to read from the chapter “The “Bind” Concept” in Functional-Programming-Simplified-Scala.pdf

This is to my understanding, as I don’t want to repeat Alvin work :) which is the best so far I have come across!

Step 1: f(0) is called which returns DebuggableWrapper(1,F)

Step 2: Call flatmap on DebuggableWrapper(1,F), which in turn calls g with 1 as value i.e g(1) which then returns DebuggableWrapper(2,G)

Step 3: Call flatmap on DebuggableWrapper(2,G), which in turn calls h with 2 as value i.e h(2) which then returns DebuggableWrapper(3,H)

Step 4: We have reached the end of the for expression generators, so now it uses map with yield expression as the function body i.e k => k

Step 5: With above step getting executed we will get DebuggableWrapper(3,H)

Step 6: Now the call stack starts unwinding the recursive calls of flatmap, starting with map returning DebuggableWrapper(3,H)

Step 7: As the call stack unwinds, the second half of the flatmap starts executing, i.e creating new instances after applying the map function. Now the call stack unwinds to Step 2 as

Step 8: As follow up the call stack unwinds to Step 1 with

Step 9: Which then returns the first flatmap call with aggregated debug info with actual calculation

I hope this gives you a different perspective on flatmap calls than usual List of List examples :)

In next post we see how the states can be handled internally without passing the previous state information, as you see in this example.

And yeah the State class is up to you to explore, happy learning!

Mageswaran, Principal Engineer @

A simple guy in pursuit of of AI and Deep Learning with Big Data tools :) @ https://www.linkedin.com/in/mageswaran1989/