In scalaz Kleisli[M[_], A, B] is a wrapper of A => M[B], which allows composition of such functions. For instance, if M[_] is monad I can compose Kleisli[M, A, B] and Kleisli[M, B, C] with >=> to get Kleisli[M, A, C].
In a nutshell, Kleisli provides fancy andThens depending on M. Is it correct ? Are there other benefits of using Kleisli?
Here are two benefits as examples—I'm sure you could come up with others.
First, it can be useful to abstract over different arrows, such as Kleisli[M, ?, ?] and ? => ?. For example, I can write a generic function that will apply an endomorphism a certain number of times.
def applyX10[Arr[_, _]: Category, A](f: Arr[A, A]) =
List.fill(10)(Endomorphic(f)).suml
Now I can use this on e.g. Int => Int or Kleisli[Option, Int, Int]:
val f = (_: Int) + 1
val k = Kleisli.kleisli[Option, Int, Int] {
case i if i % 2 == 0 => Some(i * 3)
case _ => None
}
And then:
scala> applyX10(f).run(1)
res0: Int = 11
scala> applyX10[=?>, Int](k).run(2)
res1: Option[Int] = Some(118098)
(Note that A =?> B is just an alias for Kleisli[Option, A, B].)
Second, the fact that Kleisli[F, ?, ?] has a monad instance if F does can also be useful. See for example my answer here for a demonstration of how you can use monadic composition with ReaderT, which is just an alias for Kleisli.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With