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
| Syntax | Expansion |
|---|---|
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]);