# Monoid, Functor, Applicative and Monad

## March 28, 2014

### Monoid

Given a Monoid trait `Semigroup`

``````trait Semigroup[M] {
def append(a: M, b: M): M
val zero: M
}
``````

the following should hold:

``````append(a, append(b, c)) === append(append(a, b), c)
append(a, zero) = a
append(zero, a) = a
``````

#### Monoid examples:

• `Int` with `+` and `0`
• `Int` with `*` and `1`
• `Boolean` with `||` and `false`
• `A => A` with `compose` and `identity`
• `List[A]` with `++` and `Nil`
• `String` with `+` and `""`

### Functor

#### Concept

Functor is a type class that defines how to apply a function to a value wrapped in a context(`T`).`List`, `Option`, `Ethier`, `Try` both are functor.

``````trait Functor[T[_], A] {
def fmap[B](f: A => B): Functor[T, B]

def id: T[A]
}
``````

the Functor takes two type parameters, `T[_]` which is a generic type, and a type `A` one concrete example is:

``````//List as T, A as A
case class ListFunctor[A](val id: A, xs: List[A]) extends Functor[List, A] {
def fmap[B](f: A => B): List[B] = ListFunctor(xs.map(f))
}
``````

#### Functor laws:

• `fmap id = id`

if we map the `id` function over a functor, the functor that we get back should be the same as the original functor

• for any functor F, the following should hold: `fmap (f . g) F = fmap f (fmap g F)`

composing two functions and then mapping the resulting function over a functor should be the same as first mapping one function over the functor and then mapping the other one

#### Function is Functor:

##### Function composition:

Mapping a Function over a Function will produce a new Function(function composition), just like mapping a function over a `List` will produce a `List`, mapping a function over a `Option` will produce a `Option`.

##### Lifting:

Given a `map` function with type `(A => B) => F[A] => F[B]`(`F` is a functor, it could be `List`, `Option`, or `Ethier`), we can think the `map` as a function which take a function (with type `A => B`) as parameter and return a new function just like the old one(with type `F[A] => F[B]`).

### Applicative

#### Concept

Applicative is a type class that defines how to apply a function `tf` wrapped in a context `T` to a value wrapped in a context `T`.

``````trait Applicative[T[_], A] extends Functor[T, A] {
def apply[B](f: T[A => B]): Applicative[T, B]
}
``````

#### Concept

Monad is a type class `Monad[T[_], A]` that defines how to apply a function that returns a wrapped value `A => T[B]` to a wrapped value `T[A]`.

``````trait Monad[T[_], A] extends Monoid[T, A] with Applicative[T, A] {
def flatMap[B](f: A => T[B]): Monad[T, B]
}
``````

• Left identity

Given a value `x` and a function `f`, the following should hold:

``````unit(x) flatMap f = f(x)
``````
• Right identity

Given a monad `m`, the following should hold:

``````m flatMap unit = m
``````
• Composition

Given a monad `m` and two functions `f` and `g`, the following should hold:

``````m flatMap f flatMap g == m flatMap g flatMap f
``````

``````case class ListMonad[A](val list: List[A])  extends Monad[List, A] {
//defined in Monoid

//defined in Monoid
override def id: List[A] = Nil

//defined in Functor

//defined in Applicative

}
``````

### A jounery of performance tuning KafkaStream application

In this post, we'll discuss our journey of tuning the performance of a few Kafka and KafkaStream application.### PrincipalsDivide and con...… Continue reading

#### Tracking the root cause of a topic co-partition issue

Published on May 18, 2020