Skip to main content

m_do

Macro m_do 

Source
m_do!() { /* proc-macro */ }
Expand description

Monadic do-notation.

Desugars flat monadic syntax into nested bind calls, matching Haskell/PureScript do notation.

§Syntax

m_do!(Brand {
    x <- expr;            // Bind: extract value from monadic computation
    y: Type <- expr;      // Typed bind: with explicit type annotation
    _ <- expr;            // Discard bind: sequence, discarding the result
    expr;                 // Sequence: discard result (shorthand for `_ <- expr;`)
    let z = expr;         // Let binding: pure, not monadic
    let w: Type = expr;   // Typed let binding
    expr                  // Final expression: no semicolon, returned as-is
})
  • Brand: The monad brand type (e.g., OptionBrand, VecBrand).
  • x <- expr;: Binds the result of a monadic expression to a pattern.
  • let z = expr;: A pure let binding (not monadic).
  • expr;: Sequences a monadic expression, discarding the result.
  • expr (final): The return expression, emitted as-is.

Bare pure(args) calls are automatically rewritten to pure::<Brand, _>(args).

§Statement Forms

SyntaxExpansion
x <- expr;bind::<Brand, _, _>(expr, move |x| { … })
x: Type <- expr;bind::<Brand, _, _>(expr, move |x: Type| { … })
_ <- expr;bind::<Brand, _, _>(expr, move |_| { … })
expr;bind::<Brand, _, _>(expr, move |_| { … })
let x = expr;{ let x = expr; … }
expr (final)Emitted as-is

§Generates

Nested bind calls equivalent to hand-written monadic code.

§Examples

// Invocation
use fp_library::{brands::*, functions::*};
use fp_macros::m_do;

let result = m_do!(OptionBrand {
    x <- Some(5);
    y <- Some(x + 1);
    let z = x * y;
    pure(z)
});
assert_eq!(result, Some(30));

// Expanded code
let result = bind::<OptionBrand, _, _>(Some(5), move |x| {
    bind::<OptionBrand, _, _>(Some(x + 1), move |y| {
        let z = x * y;
        pure::<OptionBrand, _>(z)
    })
});
// Invocation
// Works with any monad brand
let result = m_do!(VecBrand {
    x <- vec![1, 2];
    y <- vec![10, 20];
    pure(x + y)
});
assert_eq!(result, vec![11, 21, 12, 22]);