I have to spend more time than other (smart guys) trying to get simple topics. As a profit - getting clean description for myself - using simple (clean for non math geek) vision. I've read hundred of articles/examples/... + done few presentations on the same topic. Just want to finalize it and forget:)

*Usually articles that start with words like "monad" and "functor" quickly devolve into soup of Greek letters. That's because both are abstract concepts in a branch of mathematics called category theory and explaining them completely is a mathematical exercise.*

*JAMES IRY*

But there must be possibility to avoid complexity, to allow understanding the topic while reading in the bus or 3 minutes before falling asleep. U r welcome to the world of Monads in Scala.

## Session 1: Monad, Functor and Applicative

### 1) Install environment:

- Download Intellij Idea Community Edition

- Don't forget about Scala plugin

- Clone repository from https://stasimus@github.com/stasimus/monads-in-scala-sessions.git

- Create new Idea Project:

- New Project ...
- Import From External Sources ...
- Maven
- Path to project root
- JDK and other Buttons by default

### 2) Intro

Just giving example of Monads in ActionpersonsList filterBy {_.age > 31} map {_.team}

that later pushes to implement structures like

List("one", "two", "three", "four", "five") groupBy (_ size)

Looks nice and readable, isn't it?)

### 3) Theory

Imagine the task (world) where U have only:

- container type M[_] (_ means any), which is simple wrapper around business types A and B
- function, which helps U to get target type B from A

a) (A => B) => (M[A] => M[B])

b) (A => M[B] ) => (M[A] => M[B])

c) (M [A => B]) => (M[A] => M[B])

All this have the names

a) (A => B ) => (M[A] => M[B]) // Monad

b) (A => M[B] ) => (M[A] => M[B]) //Functor

c) (M [A => B]) => (M[A] => M[B]) //Applicative

Don't concentrate at this moment why do we need these structures

Let's try to rephrase them:

Monad: Function (A => B) applied on Container M with value A returns Container with value B (M[B])

Functor: Funct (A => M[B]) already knows how to wrap value to Container, applied on M[A] returns M[B]

Applicative: Function wrapped in Container, applied to Container M[A] returns M[B]

Please don't read it twice. Lets do a coding, determine container:

class Box[T](val value: T)

initializing real instance example:

val box = new Box("Testing")

Lets imagine situation when we want to proceed logic that gets A type and returns some processing result type B from A, that must be incapsulated in the same container type Box (Doesn't change the kind of monad, but may change it parameterized type, Box[A] can become Box[B] but should not become Container[B]). Giving it the name map:

*def map[A, B](func: A => B): Box[A] => Box[B] =*

*(box: Box[A]) => new Box(func(box.value))*

U did a first Functor! From this map is

**Functor**and Hight Order Function that gets a business function F1(A => B) as a parameter and returns a Function F2(Box[A] => Box[B]) that can be used to apply F1 to existed Box[A].

Real life example: get the size of String, long (readable) form solution example:

val in = new Box("123456789")

val rawFunc: (String) => Int = (str: String) => str.size

val mapFunc:(Box[String]) => Box[Int] = Box.map(rawFunc)

val res:Box[Int] = mapFunc(in) // Box[Int](9)

While Monads shines when they are combinable it's not a time to introduce this, please be patient while next lesson we have to create new transformation flatMap:

*def flatMap[A, B](func: A => Box[B]): Box[A] => Box[B] =*

*(box: Box[A]) => func(box.value)*

U did a first Monad! From this flatMap is

**Monad**that gets a business function F1(A => Box[B]) as a parameter and returns a Function F2(Box[A] => Box[B]) that can be used to apply F1 to existed Box[A].

Same example:

val in = new Box("12345678")

val rawFunc = (value: String) => new Box(value.size)

val flatMapFunc = Box.flatMap(rawFunc)

val res = flatMapFunc(in) // Box[Int](8)

Last task for today: imagine that 'business' function is wrapped with Container Box[A => B], to be able to work with this construction you should implement last one transformation:

*def apply[A, B](func: Box[A => B]): Box[A] => Box[B]*

*= (box: Box[A]) => new Box(func.value(box.value))*

apply like this is called Applicative! This is 3-rd and last basic transformation for today. Code without Scala's sugar is here:

val in = new Box(12345678)

val rawFunc = new Box((value: Int) => value.toString)

val applyFunc = Box.apply(rawFunc)

val res = applyFunc(in) // Box[String]("12345678")

Enjoy, it's still not complex topic,

indeed we skiped a lot of math background, reasoning why to use and main magic: Scala's approach. In the next Lesson we wil try to drive into Monadic features in Scala, where Object Oriented approach is mixed with Function Oriented.

a) (A => B ) => (M[A] => M[B]) // Monad

ReplyDeleteb) (A => M[B] ) => (M[A] => M[B]) //Functor

c) (M [A => B]) => (M[A] => M[B]) //Applicative

Shouldn't it be like that?

a) (A => B ) => (M[A] => M[B]) // Functor

b) (A => M[B] ) => (M[A] => M[B]) //Monad