# Practical examples for Scala Cats in context of shopping cart

My experience trying to learn Functional Programming was painful. Reading blogs after blogs makes it more and more confusing. So I took the practical approach to learn and this is my effort to create a reference and make it easier for anyone who passes by my blog. As shopping cart is a common appl, I have used it as the basis for these examples

- in FP we try to decouple data from behaviour
- model your domain using ADT's(Algebraic Data Types)
- Sum => choice or union using sealed abstract classes or trait

eg:`sealed abstract class CartStatus case object InProgress extends CartStatus case object Purchased extends CartStatus case object Dropped extends CartStatus`

- Product type => case class

eg:composition saying we have a and b and c`case class Checkout( item: Items, cartNumber: CartNumber)`

- Sum => choice or union using sealed abstract classes or trait
- Use type system to your advantage
`// anyval means value class. At runtime `AnyVal` gets removed only used during compile time for compile error`

### Option

```
import cats.syntax.option._
def someHttpCall(): Future {
return futureResult
}
// the value is upcast to Option[T] from Some[T]
```

### Cat 1: Functor

**What:** Functor is simply something that can be mapped over. In Scala `map`

there is no concrete implementation of functor. But there is `map`

which behaves like a functor.

**When:** When you need to map over a `Option, List`

**Eg:**

```
def getItemQuantity(item: Item, cart: Cart) {
return cart[item].quantity
}
Functor[List].map(List("iphone9", "samsung"))(_.getItemQuantity)
```

### Cat 2: Monoid

**What:** Monoid is simply a trait/class with `combine`

and `empty`

functionality that follows associative laws.

```
trait Monoid[A] {
def combine(a: A, b: B): A
def empty: A
}
```

**Eg:** Say you want to find the total number of items that makeup the shopping cart

```
def totalItems(items: List[Int]): Int = items.foldLeft(Monoid[Int].empty)(_ |+| _)
```

### Cat 3: Type-safe Equality(Eq)

**What:** Cats support both `===`

and `=!=`

for equality and non-equality respectively

**Eg:** ```// custom equality

import cats.instances.long._

implicit val productEq: Eq(Product) =

Eq.instance[Product] {(product1, product2) =>

product1.name === product2.name

product1.sku === product2.sku

}