//@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) // Kleisli composition #[infix(right, 9)] let (<=<) g f x : [Monad m] -> (b -> m c) -> (a -> m b) -> a -> m c = g =<< f x #[infix(left, 9)] let (>=>) f g x : [Monad m] -> (a -> m b) -> (b -> m c) -> a -> m c = f x >>= g { Monad, flat_map, (>>=), (=<<), join, (<=<), (>=>), }