Annotation 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.

Since:
6.0.0
  • Optional Element Summary

    Optional Elements
    Modifier and Type
    Optional Element
    Description
    The flatMap-shaped bind method name.
    The map method name.
    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.
  • Element Details

    • bind

      String bind
      The flatMap-shaped bind method name. Empty means the structural default flatMap.
      Default:
      ""
    • map

      String map
      The map method name. Empty means the structural default map.
      Default:
      ""
    • unit

      String unit
      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().

      Default:
      ""