gluon 0.13.1

A static, type inferred programming language for application embedding
Documentation
//@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
}