+ * or it can be constructed from the following convenient
+ * forms called handler tags, where `ActionType` is a type in the variant ActionT:
+ *
+ * - `passDown<ActionType>()` will dispatch the action to the underlying context, and return the promise returned from the dispatch. Actions other than ActionType will not be matched.
+ * - `returnResolved<ActionType>(DataT data)` will return a Promise that is resolved and contains `data` when the action is of ActionType. Actions other than ActionType will not be matched.
+ * - `returnEmpty<ActionType>()` is equivalent to `returnResolved<ActionType>({}).
+ * - `makeHandler<ActionType>(Func func)`, where `func` has any of the following signature:
+ * 1. `HandlerResult<PromiseT>(PH &, ContextT &, ActionType)`. It will be called when the action is of ActionType, and the return value from it will be the result. Actions other than ActionType will not be matched and will not be executed on this function.
+ * 2. `PromiseT(PH &, ContextT &, ActionType)`. It will be called when the action is of ActionType, and in this case it will always be a match, and the result is a HandlerResult with the returned promise. Actions other than ActionType will not be matched and will not be executed on this function.
+ * 3. `HandlerResult<PromiseT>(ActionType)`. Same as the first case, but only the action is passed to the function, and not the promise handler and the context.
+ * 4. `PromiseT(ActionType)`. Same as the second case, but only the action is passed to the function, and not the promise handler and the context.
+ * 5. `DataT(ActionType)`. Same as the fourth case, but the promise returned is one that is resolved and contains the return value of the function.
+ * 6. `void(ActionType)`. Same as the fourth case, but the promise returned is one that is resolved and contains a default-constructed `DataT`.
+ */
struct Handler : public std::function<HandlerResultT(PH &, ContextT &, ActionT)>
{
using BaseT = std::function<HandlerResultT(PH &, ContextT &, ActionT)>;