anchor.diff:  
   Great the `map` function is allowing a type of function composition, but now what happens when we want to compose more functions that return our functor?
   [source,scala]
  -
   ----
   val f: Int => Int = 
   x => x + 5
  
positive.code: 
  gof(6)
  > true
  
  ----
  The essence of functional programming is doing this, create programs from composing small functions into larger functions, which provide us with the type safety and the determinism of pure functions. but what happens when we have functions that require to handle a side effect and return the appropriate type constructor?
  
  [source, scala]
  ----
  val f: Int => Int = 
  
negative.code: [source,scala]
  ----
  trait Monad[F[_]] extends Functor[F] {
  def pure[A](a: A): F[A]
  def map[A, B](M: F[A])(f: A => B): F[B] =
  flatMap(M)(x => pure(f(x)))
  def flatMap[A, B](M: F[A])(f: A => F[B]): F[B]
  }
  ----
  = Left identity:
  If we lift a pure value, and then flatMap with a monadic function (a function with the signature `A => F[A]` where `A` is a pure value and `F[_]` a Monad type constructor) then that must be equal to just passing the pure value through the monadic function:
  [source,scala]
  ----
  pure(a).flatMap(f) === f(a)
  ----
  = Right identity:	
  If we take a monadic value `m` (a pure value that has been lifted to the context of a monad, has signature `M[A]`) and flatMap the `pure` function from it, that must be equal to the original `m`:
  [source,scala]
  ----
  m.flatMap(pure) === m
  ----
  = Associativity:	
  Let `m` be a monadic value, and `f` and `g` monadic functions, then it must be that flat mapping `f` and then `g` be equal to composing `f` and `g` first (using flatMap) and then using the resulting monadic function to flatMap from `m`:
  [source,scala]
  ----
  m.flatMap(f).flatMap(g) === m.flatMap(\x => f(x).flatMap g)
  