LYAHFGG:

When we were learning about the monad laws, we said that the `<=<` function is just like composition, only instead of working for normal functions like `a -> b`, it works for monadic functions like `a -> m b`.

In Cats there’s a special wrapper for a function of type `A => F[B]` called Kleisli:

``````/**
* Represents a function `A => F[B]`.
*/
final case class Kleisli[F[_], A, B](run: A => F[B]) { self =>

....
}

object Kleisli extends KleisliInstances with KleisliFunctions

private[data] sealed trait KleisliFunctions {

def pure[F[_], A, B](x: B)(implicit F: Applicative[F]): Kleisli[F, A, B] =
Kleisli(_ => F.pure(x))

def ask[F[_], A](implicit F: Applicative[F]): Kleisli[F, A, A] =
Kleisli(F.pure)

def local[M[_], A, R](f: R => R)(fa: Kleisli[M, R, A]): Kleisli[M, R, A] =
Kleisli(f andThen fa.run)
}
``````

We can use the `Kleisli()` constructor to construct a `Kliesli` value:

``````scala> import cats._, cats.data._, cats.implicits._
import cats._
import cats.data._
import cats.implicits._
scala> val f = Kleisli { (x: Int) => (x + 1).some }
f: cats.data.Kleisli[Option,Int,Int] = Kleisli(\$\$Lambda\$3947/476696272@67a14ec8)
scala> val g = Kleisli { (x: Int) => (x * 100).some }
g: cats.data.Kleisli[Option,Int,Int] = Kleisli(\$\$Lambda\$3948/690043337@74b181a)``````

We can then compose the functions using `compose`, which runs the right-hand side first:

``````scala> 4.some >>= (f compose g).run
res0: Option[Int] = Some(401)``````

There’s also `andThen`, which runs the left-hand side first:

``````scala> 4.some >>= (f andThen g).run
res1: Option[Int] = Some(500)``````

Both `compose` and `andThen` work like function composition but note that they retain the monadic context.

#### lift method

Kleisli also has some interesting methods like `lift`, which allows you to lift a monadic function into another applicative functor. When I tried using it, I realized it’s broken, so here’s the fixed version #354:

``````  def lift[G[_]](implicit G: Applicative[G]): Kleisli[λ[α => G[F[α]]], A, B] =
Kleisli[λ[α => G[F[α]]], A, B](a => Applicative[G].pure(run(a)))
``````

Here’s how we can use it:

``````scala> val l = f.lift[List]
l: cats.data.Kleisli[[α]List[Option[α]],Int,Int] = Kleisli(cats.data.Kleisli\$\$Lambda\$3951/723364368@4f76e28c)
scala> List(1, 2, 3) >>= l.run
res2: List[Option[Int]] = List(Some(2), Some(3), Some(4))``````