embracing-nondeterminism-code/src/main/scala/green/thisfieldwas/embracingnondeterminism/syntax/monad.scala

52 lines
1.4 KiB
Scala

package green.thisfieldwas.embracingnondeterminism.syntax
import green.thisfieldwas.embracingnondeterminism.control.Monad
object monad {
implicit class FlatMapOps[F[_], A](val fa: F[A]) extends AnyVal {
/** Convenience method to call `flatMap()` directly on a context.
*
* @param f
* The function to map against instances within the context.
* @param F
* The context Monad instance.
* @tparam B
* The term of instances contained within the produced context.
* @return
* The produced context.
*/
def flatMap[B](f: A => F[B])(implicit F: Monad[F]): F[B] = F.flatMap(fa)(f)
}
implicit class FlattenOps[F[_], A](val ffa: F[F[A]]) extends AnyVal {
/** Convenience method to directly flatten a nested context.
*
* @param F
* The context Monad instance.
* @return
* The flattened context.
*/
def flatten(implicit F: Monad[F]): F[A] = F.flatten(ffa)
}
implicit class KleisliCompositionOps[F[_], A, B](val f: A => F[B]) extends AnyVal {
/** Kleisli composition right-arrow operator.
*
* @param g
* The second function to compose.
* @param F
* The context Monad instance.
* @tparam C
* The final context term.
* @return
* The context produced by the second function `g`.
*/
def >=>[C](g: B => F[C])(implicit F: Monad[F]): A => F[C] =
(x: A) => F.flatMap(f(x))(g)
}
}