//@NO-IMPLICIT-PRELUDE
//! Implementation of the `Monad` type
let { Bool } = import! std.types
let { Applicative, wrap } = import! std.applicative
/// A generalised interface for imperatively sequencing actions
#[implicit]
type Monad (m : Type -> Type) = {
applicative : Applicative m,
/// This can be seen as akin to sequential variable binding in an
/// imperative language. For example in Javascript:
///
/// ```js
/// var x = call_fallible("hello");
/// do_something(x);
/// ```
///
/// In gluon this would look like:
///
/// ```gluon
/// result.monad.flat_map (\x -> do_something x) (call_fallible "hello")
/// ```
///
/// Note that it is sometimes more ergonomic to use the `(>>=)` operator:
///
/// ```gluon
/// let { (>>=) } = import! std.prelude
///
/// call_fallible "hello" >>= (\x -> do_something x)
/// ```
///
/// # Note
///
/// * Known as `(=<<) or `flip (>>=)` in Haskell
/// * Known as `Option::and_then` and `Result::and_then` in Rust
flat_map : forall a b . (a -> m b) -> m a -> m b
}
let flat_map ?m : [Monad m] -> (a -> m b) -> m a -> m b = m.flat_map
#[infix(right, 1)]
let (=<<) : [Monad m] -> (a -> m b) -> m a -> m b = flat_map
#[infix(left, 1)]
let (>>=) x f : [Monad m] -> m a -> (a -> m b) -> m b = flat_map f x
let join mm : [Monad m] -> m (m a) -> m a = mm >>= (\x -> x)
{
Monad,
flat_map, (>>=), (=<<), join
}