 keywordsalad
/
embracing-nondeterminism-code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

#### 74 lines 2.9 KiB Raw Permalink Blame History

 `package green.thisfieldwas.embracingnondeterminism.control` ``` ``` `/** Monad is a specialization of Functor where the type contained within the` ` * context, `A` in `F[A]`, is known specifically to have some type of `F[A]`.` ` * That is, the Functor is nested as `F[F[A]]`. The Monad defines a function` ` * called `flatten()` which joins the inner `F[A]` with the outer `F[_]`, and` ` * defines a specialization of the `map()` function called `flatMap()` which` ` * permits the usage of a function producing a context: `f: A => F[B]`.` ` *` ` * By permitting the context to nest within itself, the inner context may alter` ` * the outer context's case when flattened. This allows for the function `f: A` ` * \=> F[B]` to control whether computation proceeds or halts against the` ` * context.` ` *` ` * Monads must define one or both of `flatten()` or `flatMap()`, as one is used` ` * to define the other.` ` *` ` * @tparam F` ` * The context type.` ` */` `trait Monad[F[_]] extends Applicative[F] {` ``` ``` ` /** Map the contents of this context with a function which returns its results` ` * in a new instance of the context. This new context is joined with the` ` * current context.` ` *` ` * If the context `fa` is in the desired case, two things can happen based on` ` * the output of function `f`:` ` *` ` * 1. If `f` returns `F[B]` in the desired case, then `flatMap()` returns` ` * `F[B]` in the desired case.` ` * 1. If `f` returns `F[B]` in the undesired case, then `flatMap()` returns` ` * `F[B]` in the undesired case and further computation is halted.` ` *` ` * If the context `fa` is in the undesired case, then `f` does not apply and` ` * no computation occurs.` ` *` ` * @param fa` ` * The context to map.` ` * @param f` ` * The function to map the contents of the context.` ` * @tparam A` ` * The term of the instances within the context.` ` * @tparam B` ` * The term of the instances within the context produced by the function.` ` * @return` ` * The context produced by the function joined with the context `fa`.` ` */` ` def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B] = flatten(map(fa)(f))` ``` ``` ` /** Flattens a nested context.` ` *` ` * Based on the states of the contexts, a few things may happen:` ` * 1. If the outer context is in the undesired case, then a flattened` ` * context in the undesired case is produced.` ` * 1. If the inner context is in the undesired case, then a flattened` ` * context in the undesired case is produced. 3. If both contexts are in` ` * the desired case, then a flattened context in the desired case is` ` * produced.` ` *` ` * @param ffa` ` * The nested context.` ` * @tparam A` ` * The term contained by the inner context.` ` * @return` ` * A flattened context containing term `A`.` ` */` ` def flatten[A](ffa: F[F[A]]): F[A] = flatMap(ffa)(fa => fa)` `}` ``` ``` `object Monad {` ``` ``` ` def apply[F[_]: Monad]: Monad[F] = implicitly[Monad[F]]` ```} ``` ``` ```