Typed machines

States and events are enums, and an illegal assembly does not compile.

Document workflow

This is the machine Document Workflow runs. InReview and Approval are composites: all[InReview] cancels to Draft, and all[Approval] abandons to Cancelled.

ApprovalInReviewSubmitForReviewApproveReviewApprovePublicationSubmitForReviewCancelReviewCancelReviewCancelReviewAbandonAbandonArchiveRejectPublicationAssignReviewerRequestChangesResubmitAfterChanges

Install

libraryDependencies += "rocks.earlyeffect" %% "mechanoid" % "0.8.0"
libraryDependencies += "dev.zio" %% "zio" % "2.1.26"

libraryDependencies += "rocks.earlyeffect" %%% "mechanoid" % "0.8.0"
libraryDependencies += "dev.zio" %%% "zio" % "2.1.26"

libraryDependencies += "rocks.earlyeffect" %%% "mechanoid-web" % "0.8.0"
libraryDependencies += "rocks.earlyeffect" %% "mechanoid-postgres" % "0.8.0"

Machine.apply

Machine.apply is the public constructor. Citing that method expands the inline macro, which rejects a placeholder assembly, so the panel is mechanoid.machine.Machine, cut after apply.

mechanoid.machine.Machine
object Machine:

  /** Create a Machine from a validated Assembly.
    *
    * This is the ONLY public way to create a Machine. The assembly must be created via the `assembly` or `assemblyAll`
    * macros, which perform compile-time validation of transitions.
    *
    * @tparam S
    *   The state type (must have Finite instance)
    * @tparam E
    *   The event type (must have Finite instance)
    * @param assembly
    *   A validated assembly created via `assembly()` or `assemblyAll()`
    * @return
    *   A runnable Machine
    *
    * @example
    *   {{{
    * import mechanoid.Mechanoid.*
    *
    * // Using assembly()
    * val machine = Machine(assembly[State, Event](
    *   Idle via Start to Running,
    *   Running via Stop to Idle,
    * ))
    *
    * // Using assemblyAll with block syntax
    * val machine2 = Machine(assemblyAll[State, Event]:
    *   Idle via Start to Running
    *   Running via Stop to Idle
    * )
    *   }}}
    */
  inline def apply[S, E](inline assembly: Assembly[S, E])(using
      inline finiteS: Finite[S],
      inline finiteE: Finite[E],
  ): Machine[S, E] =
    ${ MachineMacros.applyImpl[S, E]('assembly, 'finiteS, 'finiteE) }

…

View source