@Documented
@Incubating
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Monadic
Marks a type as participating in monadic comprehensions (the DO macro).
Optional members declare the bind/map method names when they diverge from the
structural convention (flatMap/map). When both are omitted, the
annotation merely opts the type in and the structural defaults apply.
Modelled on Reducer: a pure marker, read by tooling,
with no AST transformation. The runtime dispatcher and the type checker match
this annotation by simple name (Monadic), exactly as
groovy.typecheckers.CombinerChecker matches @Reducer/@Associative.
Lawful carriers and value equality. A comprehension composes monadic
values, which are only meaningful up to value equality: two carriers
wrapping equal contents denote the same result. A data-style carrier should
therefore provide structural equals/hashCode (Groovy's
== dispatches to equals); without them, results compare by
identity and the laws — right identity and functor identity in
particular — are reference-unequal and silently fail to hold. This does
not apply to effectful or lazy carriers (Stream,
CompletableFuture, Awaitable), whose laws hold only up to
observational equivalence and for which value equality is neither available
nor expected.
As with Associative and Reducer, this annotation asserts that the carrier is lawful (the left/right identity and associativity laws); it does not prove it. The assertion is intended to be backed by tests.
The flatMap-shaped bind method name. Empty means the structural default flatMap.
The map method name. Empty means the structural default map.
The name of the carrier's unit (a.k.a. of/pure/return)
factory: a static, single-argument method that lifts a bare value into the
carrier. Empty means undeclared.
The DO macro does not use this member — its body
yields the carrier explicitly, so no implicit lifting is performed. Unlike
bind() and map(), the unit cannot be recovered
structurally: it is a producer (value -> carrier), commonly a
static factory (for example Optional.of), and for a multi-case
carrier several factories share that shape (an Either's
left/right). Naming it lets law-deriving or law-checking
tooling synthesize the unit-dependent laws (left identity, right identity);
the unit-free laws (associativity, the functor laws) do not need it. This
is the @Monadic analogue of Reducer.zero.