这里有两个好处作为例子——我相信你可以想出其他的。
首先,抽象不同的箭头可能很有用,例如Kleisli[M, ?, ?] 和? => ?。例如,我可以编写一个泛型函数,该函数将应用自同态一定次数。
def applyX10[Arr[_, _]: Category, A](f: Arr[A, A]) =
List.fill(10)(Endomorphic(f)).suml
现在我可以在例如Int => Int 或 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
}
然后:
scala> applyX10(f).run(1)
res0: Int = 11
scala> applyX10[=?>, Int](k).run(2)
res1: Option[Int] = Some(118098)
(注意A =?> B 只是Kleisli[Option, A, B] 的别名。)
其次,如果F 确实存在,Kleisli[F, ?, ?] 具有 monad 实例这一事实也很有用。例如,请参阅 my answer here,了解如何将一元组合与 ReaderT 一起使用,这只是 Kleisli 的别名。