Skip to content

Builtins

The canonical prelude effects and their reference handlers.

builtins

Canonical QIEC prelude effects and their small reference handlers.

The declarations in this module are stable structural data. The factory functions produce process-local :class:~quivers.qiec.evaluator.RuntimeHandler attachments; samplers, distributions, semirings, and observation tables consequently never become serializable QIEC fields.

RANDOM module-attribute

RANDOM = _effect_ref('Random')

Random: the prelude interface for drawing a value at a sample site.

RANDOM_SAMPLE module-attribute

RANDOM_SAMPLE = _operation_id(RANDOM, 'sample')

Random.sample: draw a value of type A at a site from a Sampleable[A].

RANDOM_EFFECT module-attribute

RANDOM_EFFECT = EffectDef(RANDOM, (), (OperationDef(RANDOM_SAMPLE, 'sample', (_A_BINDER,), (ArgumentDef('site', SITE_A), ArgumentDef('sampleable', SAMPLEABLE_A)), A),))

The declaration of :data:RANDOM.

SCORE module-attribute

SCORE = _effect_ref('Score')

Score: the prelude interface for adding a log-density contribution.

SCORE_ADD module-attribute

SCORE_ADD = _operation_id(SCORE, 'add')

Score.add: add one LogWeight to the running score.

SCORE_EFFECT module-attribute

SCORE_EFFECT = EffectDef(SCORE, (), (OperationDef(SCORE_ADD, 'add', (), (ArgumentDef('weight', LOG_WEIGHT),), UNIT),))

The declaration of :data:SCORE.

STATE_EFFECT_REF module-attribute

STATE_EFFECT_REF = _effect_ref('State')

State[S]: the prelude interface for one mutable cell of type S.

STATE_GET module-attribute

STATE_GET = _operation_id(STATE_EFFECT_REF, 'get')

State.get: read the cell.

STATE_PUT module-attribute

STATE_PUT = _operation_id(STATE_EFFECT_REF, 'put')

State.put: overwrite the cell.

STATE_EFFECT module-attribute

STATE_EFFECT = EffectDef(STATE_EFFECT_REF, (_S_BINDER,), (OperationDef(STATE_GET, 'get', (), (), STATE), OperationDef(STATE_PUT, 'put', (), (ArgumentDef('value', STATE),), UNIT)))

The declaration of :data:STATE_EFFECT_REF; :func:state_effect applies it.

ABORT module-attribute

ABORT = _effect_ref('Abort')

Abort[P]: the prelude interface for stopping with a payload of type P.

ABORT_ABORT module-attribute

ABORT_ABORT = _operation_id(ABORT, 'abort')

Abort.abort: stop the computation with an error payload.

ABORT_EFFECT module-attribute

ABORT_EFFECT = EffectDef(ABORT, (_P_BINDER,), (OperationDef(ABORT_ABORT, 'abort', (_A_BINDER,), (ArgumentDef('error', PAYLOAD),), A),))

The declaration of :data:ABORT; :func:abort_effect applies it.

CHOOSE module-attribute

CHOOSE = _effect_ref('Choose')

Choose: the prelude interface for nondeterministic choice.

CHOOSE_CHOOSE module-attribute

CHOOSE_CHOOSE = _operation_id(CHOOSE, 'choose')

Choose.choose: pick one of a collection of alternatives.

CHOOSE_EFFECT module-attribute

CHOOSE_EFFECT = EffectDef(CHOOSE, (), (OperationDef(CHOOSE_CHOOSE, 'choose', (_A_BINDER,), (ArgumentDef('alternatives', CHOICES_A),), A),))

The declaration of :data:CHOOSE.

WEIGHT module-attribute

WEIGHT = _effect_ref('Weight')

Weight[K]: the prelude interface for accumulating a semiring weight of type K.

WEIGHT_ADD module-attribute

WEIGHT_ADD = _operation_id(WEIGHT, 'add')

Weight.add: fold one weight into the running total in the handler's semiring.

WEIGHT_EFFECT module-attribute

WEIGHT_EFFECT = EffectDef(WEIGHT, (_K_BINDER,), (OperationDef(WEIGHT_ADD, 'add', (), (ArgumentDef('weight', K),), UNIT),))

The declaration of :data:WEIGHT; :func:weight_effect applies it.

COMPUTE module-attribute

COMPUTE = _effect_ref('Compute')

Compute[X, A]: the prelude interface for a host computation; see :data:COMPUTE_EFFECT.

COMPUTE_APPLY module-attribute

COMPUTE_APPLY = _operation_id(COMPUTE, 'apply')

Compute.apply: run the host computation on an argument of type X.

COMPUTE_EFFECT module-attribute

COMPUTE_EFFECT = EffectDef(COMPUTE, (_X_BINDER, _ANSWER_BINDER), (OperationDef(COMPUTE_APPLY, 'apply', (), (ArgumentDef('argument', INPUT),), ANSWER),))

Compute[X, A]: a host computation as an effect interface.

A morphism, a closure, or any other process-local function a program depends on is not a kernel value; performing apply on an instance of this interface asks the handler installed for it, which a runtime provider supplies, so the dependence is explicit in the row.

PARAM module-attribute

PARAM = _effect_ref('Param')

Param: the prelude interface for learned parameter lookup; see :data:PARAM_EFFECT.

PARAM_GET module-attribute

PARAM_GET = _operation_id(PARAM, 'get')

Param.get: read a learned parameter by name.

PARAM_EFFECT module-attribute

PARAM_EFFECT = EffectDef(PARAM, (), (OperationDef(PARAM_GET, 'get', (_A_BINDER,), (ArgumentDef('name', STRING),), A),))

Param: learned parameter lookup as an effect.

A host computation reads each learned tensor it depends on by name through get, so a handler between it and the parameter store can answer with a perturbed value, as a prior lift does, or record the read.

BUILTIN_EFFECTS module-attribute

Every prelude interface declaration, which every module may name without declaring.

SEARCH_REDUCTIONS module-attribute

SEARCH_REDUCTIONS: tuple[str, ...] = ('logsumexp', 'max', 'or', 'sum')

The semiring additions :func:search_handler may combine its shots by.

ScoreAccumulator dataclass

ScoreAccumulator(total: object, contributions: list[object] = list())

Mutable result owned by one installed Score handler.

PARAMETER DESCRIPTION
total

The running combination of every contribution so far, starting at the handler's identity.

TYPE: object

contributions

Every contribution in the order it was added.

TYPE: list[object] DEFAULT: list()

MissingValuePolicy

Bases: str, Enum

What a condition handler does with a sample site it has no observation for.

FORWARD passes the request to an outer handler; ERROR rejects it.

ExtraValuePolicy

Bases: str, Enum

What a handler does with a supplied value no sample site consumed.

IGNORE discards it; ERROR rejects the run when the handled computation returns.

ReplayPolicy

Bases: str, Enum

Whether a replayed value is scored as well as clamped.

CLAMP_AND_SCORE sends the replayed value's log density to a Score instance; CLAMP_NO_SCORE and INTERVENE replay it without scoring.

TraceEvent dataclass

TraceEvent(address: tuple[str, tuple[tuple[str, str | int], ...], tuple[int, ...]], instance: EffectInstanceId, operation: OperationId, arguments: tuple[object, ...], result: object, mode: str)

One recorded request and the value produced for it.

PARAMETER DESCRIPTION
address

The request's dynamic key: its static site, address frames, and resumption path.

TYPE: tuple[str, tuple[tuple[str, str | int], ...], tuple[int, ...]]

instance

The effect instance the request was performed on.

TYPE: EffectInstanceId

operation

The operation requested.

TYPE: OperationId

arguments

The evaluated value arguments.

TYPE: tuple[object, ...]

result

The value produced for the request.

TYPE: object

mode

How the value was produced, such as "forwarded".

TYPE: str

TraceRecorder dataclass

TraceRecorder(events: list[TraceEvent] = list())

Ordered trace; repeated dynamic addresses remain observable as events.

PARAMETER DESCRIPTION
events

The recorded events, in order; empty to start.

TYPE: list[TraceEvent] DEFAULT: list()

record

record(request: RuntimeRequest, result: object, *, mode: str) -> object

Record one request and the value produced for it.

PARAMETER DESCRIPTION
request

The request being answered and its arguments.

TYPE: RuntimeRequest

result

The value produced for the request.

TYPE: object

mode

How the value was produced.

TYPE: str

RETURNS DESCRIPTION
object

The value, unchanged, after recording. Returned so the caller can use this in place of the value it passed.

Source code in src/quivers/qiec/builtins.py
def record(self, request: RuntimeRequest, result: object, *, mode: str) -> object:
    """Record one request and the value produced for it.

    Parameters
    ----------
    request
        The request being answered and its arguments.
    result
        The value produced for the request.
    mode
        How the value was produced.

    Returns
    -------
    object
        The value, unchanged, after recording. Returned so the caller can
        use this in place of the value it passed.
    """
    self.events.append(
        TraceEvent(
            request.address,
            request.instance,
            request.operation,
            request.arguments,
            result,
            mode,
        )
    )
    return result

StateCell dataclass

StateCell(value: object)

The mutable cell owned by one installed State handler.

PARAMETER DESCRIPTION
value

The current state.

TYPE: object

Aborted dataclass

Aborted(error: object)

The default answer of an abort handler, wrapping the abort payload.

PARAMETER DESCRIPTION
error

The payload the computation aborted with.

TYPE: object

WeightAccumulator dataclass

WeightAccumulator(total: object, contributions: list[object] = list())

Mutable result owned by one installed Weight handler.

PARAMETER DESCRIPTION
total

The running combination of every contribution so far, starting at the handler's identity.

TYPE: object

contributions

Every contribution in the order it was added.

TYPE: list[object] DEFAULT: list()

state_effect

state_effect(state_type: TypeExpr) -> EffectRef

Construct the concrete State[state_type] interface.

PARAMETER DESCRIPTION
state_type

The type to instantiate the interface's binder at.

TYPE: TypeExpr

RETURNS DESCRIPTION
EffectRef

The saturated application.

RAISES DESCRIPTION
TypeError

If the argument is not a type.

ValueError

If it is ill-kinded.

Source code in src/quivers/qiec/builtins.py
def state_effect(state_type: TypeExpr) -> EffectRef:
    """Construct the concrete ``State[state_type]`` interface.

    Parameters
    ----------
    state_type : TypeExpr
        The type to instantiate the interface's binder at.

    Returns
    -------
    EffectRef
        The saturated application.

    Raises
    ------
    TypeError
        If the argument is not a type.
    ValueError
        If it is ill-kinded.
    """
    return STATE_EFFECT.apply((state_type,))

abort_effect

abort_effect(error_type: TypeExpr) -> EffectRef

Construct the concrete Abort[error_type] interface.

PARAMETER DESCRIPTION
error_type

The type to instantiate the interface's binder at.

TYPE: TypeExpr

RETURNS DESCRIPTION
EffectRef

The saturated application.

RAISES DESCRIPTION
TypeError

If the argument is not a type.

ValueError

If it is ill-kinded.

Source code in src/quivers/qiec/builtins.py
def abort_effect(error_type: TypeExpr) -> EffectRef:
    """Construct the concrete ``Abort[error_type]`` interface.

    Parameters
    ----------
    error_type : TypeExpr
        The type to instantiate the interface's binder at.

    Returns
    -------
    EffectRef
        The saturated application.

    Raises
    ------
    TypeError
        If the argument is not a type.
    ValueError
        If it is ill-kinded.
    """
    return ABORT_EFFECT.apply((error_type,))

weight_effect

weight_effect(weight_type: TypeExpr) -> EffectRef

Construct the concrete Weight[weight_type] interface.

PARAMETER DESCRIPTION
weight_type

The type to instantiate the interface's binder at.

TYPE: TypeExpr

RETURNS DESCRIPTION
EffectRef

The saturated application.

RAISES DESCRIPTION
TypeError

If the argument is not a type.

ValueError

If it is ill-kinded.

Source code in src/quivers/qiec/builtins.py
def weight_effect(weight_type: TypeExpr) -> EffectRef:
    """Construct the concrete ``Weight[weight_type]`` interface.

    Parameters
    ----------
    weight_type : TypeExpr
        The type to instantiate the interface's binder at.

    Returns
    -------
    EffectRef
        The saturated application.

    Raises
    ------
    TypeError
        If the argument is not a type.
    ValueError
        If it is ill-kinded.
    """
    return WEIGHT_EFFECT.apply((weight_type,))

draw_handler

draw_handler(result_validator: RuntimeValidator, *, draw: Callable[[object, object, RuntimeRequest], object] | None = None, answer_type: TypeExpr = ANSWER, duplicable_context: bool = False, key: str = 'draw') -> RuntimeHandler

Interpret Random.sample by drawing exactly once.

PARAMETER DESCRIPTION
result_validator

Checks the value a resumption carries inhabits the operation's result type.

TYPE: RuntimeValidator

draw

Supplies the drawn value, given the site, the sampleable, and the request. None uses the sampleable's own reparameterised or plain sampling interface.

TYPE: Callable[[object, object, RuntimeRequest], object] | None DEFAULT: None

answer_type

What the handler answers with.

TYPE: TypeExpr DEFAULT: ANSWER

duplicable_context

Whether the handler's own state may be copied for a multi-shot resumption. Asserted rather than inferred: copying a handler owning mutable state would let two shots share it.

TYPE: bool DEFAULT: False

key

Distinguishes this handler from others of the same name, entering its derived identity.

TYPE: str DEFAULT: 'draw'

RETURNS DESCRIPTION
RuntimeHandler

The attachment, ready to bind into a runtime environment.

Source code in src/quivers/qiec/builtins.py
def draw_handler(
    result_validator: RuntimeValidator,
    *,
    draw: Callable[[object, object, RuntimeRequest], object] | None = None,
    answer_type: TypeExpr = ANSWER,
    duplicable_context: bool = False,
    key: str = "draw",
) -> RuntimeHandler:
    """Interpret ``Random.sample`` by drawing exactly once.

    Parameters
    ----------
    result_validator
        Checks the value a resumption carries inhabits the
        operation's result type.
    draw
        Supplies the drawn value, given the site, the sampleable, and
        the request. None uses the sampleable's own reparameterised or
        plain sampling interface.
    answer_type
        What the handler answers with.
    duplicable_context
        Whether the handler's own state may be copied for a
        multi-shot resumption. Asserted rather than inferred: copying a
        handler owning mutable state would let two shots share it.
    key
        Distinguishes this handler from others of the same name,
        entering its derived identity.

    Returns
    -------
    RuntimeHandler
        The attachment, ready to bind into a runtime environment.
    """
    definition = _handler_def(
        "Random.draw",
        RANDOM,
        ((RANDOM_SAMPLE, ResumptionGrade.LINEAR),),
        key=key,
        input_type=answer_type,
        output_type=answer_type,
        telescope=_generic_binders(answer_type=answer_type),
    )

    def sample(
        request: RuntimeRequest,
        resume: Resumption,
        _context: ClauseContext,
    ) -> object:
        """Answer a `Random.sample` request.

        Parameters
        ----------
        request
            The request being answered and its arguments.
        resume
            The continuation, invoked within the clause's declared grade.
        _context
            Runtime services, unused by this clause.

        Returns
        -------
        object
            What the resumed computation produced.

        Raises
        ------
        InvalidHandlerError
            If the request does not carry a site and a sampleable, or the
            default draw finds no sampling interface on the sampleable.
        """
        site, sampleable = _expect_arguments(request, 2, definition.name)
        value = (
            draw(site, sampleable, request)
            if draw is not None
            else _default_draw(sampleable)
        )
        return TailResume(value)

    return RuntimeHandler(
        definition,
        {RANDOM_SAMPLE: RuntimeClause(sample, result_validator)},
        duplicable_context=duplicable_context,
    )

add_weights

add_weights(left: object, right: object) -> object

Add two log weights, entrywise over tensors of them.

PARAMETER DESCRIPTION
left

A float, or nested tuples of floats.

TYPE: object

right

A float, or nested tuples of floats shaped like left when both are tensors.

TYPE: object

RETURNS DESCRIPTION
object

The entrywise sum; a scalar broadcasts over a tensor.

RAISES DESCRIPTION
RuntimeTypeMismatch

If two tensors differ in shape.

Source code in src/quivers/qiec/builtins.py
def add_weights(left: object, right: object) -> object:
    """Add two log weights, entrywise over tensors of them.

    Parameters
    ----------
    left : object
        A float, or nested tuples of floats.
    right : object
        A float, or nested tuples of floats shaped like ``left`` when
        both are tensors.

    Returns
    -------
    object
        The entrywise sum; a scalar broadcasts over a tensor.

    Raises
    ------
    RuntimeTypeMismatch
        If two tensors differ in shape.
    """
    if isinstance(left, tuple) and isinstance(right, tuple):
        if len(left) != len(right):
            raise RuntimeTypeMismatch(
                f"weights of lengths {len(left)} and {len(right)} cannot be added"
            )
        return tuple(add_weights(a, b) for a, b in zip(left, right, strict=True))
    if isinstance(left, tuple):
        return tuple(add_weights(item, right) for item in left)
    if isinstance(right, tuple):
        return tuple(add_weights(left, item) for item in right)
    return cast(float, left) + cast(float, right)

enumerate_handler

enumerate_handler(result_validator: RuntimeValidator, *, answer_type: TypeExpr = ANSWER, weight_type: TypeExpr | None = None, reduction: str = 'logsumexp', key: str = 'enumerate') -> RuntimeHandler

Interpret Random.sample by aggregating over a finite support.

The handled computation must answer with its value paired with the log weight it accumulated, as the collecting Weight handler answers. The clause resumes once per support value, adds each shot's weight to the prior log probability of its value, and aggregates the shots by the reduction: logsumexp answers the log of the summed probabilities, the marginal; sum the sum of the weighted shots; mean their average. The aggregate is totalled over the plate's positions when the latent is plated, or kept one per position when a weight type is given, which is what a marginalization nested in a grouped one adds to its group's weights.

PARAMETER DESCRIPTION
result_validator

Checks the value a resumption carries inhabits the operation's result type.

TYPE: RuntimeValidator

answer_type

What the handled computation answers with.

TYPE: TypeExpr DEFAULT: ANSWER

weight_type

The type of the per-position weights the clause answers with, the collected weights' own tensor type, whose shape the answer takes from the shots' weights; None totals the positions into one LogWeight.

TYPE: TypeExpr | None DEFAULT: None

reduction

How the shots aggregate: "logsumexp", "sum", or "mean".

TYPE: str DEFAULT: 'logsumexp'

key

Distinguishes this handler from others of the same name.

TYPE: str DEFAULT: 'enumerate'

RETURNS DESCRIPTION
RuntimeHandler

The attachment.

RAISES DESCRIPTION
ValueError

If the reduction is not one of the three.

Source code in src/quivers/qiec/builtins.py
def enumerate_handler(
    result_validator: RuntimeValidator,
    *,
    answer_type: TypeExpr = ANSWER,
    weight_type: TypeExpr | None = None,
    reduction: str = "logsumexp",
    key: str = "enumerate",
) -> RuntimeHandler:
    """Interpret ``Random.sample`` by aggregating over a finite support.

    The handled computation must answer with its value paired with the
    log weight it accumulated, as the collecting ``Weight`` handler
    answers. The clause resumes once per support value, adds each shot's
    weight to the prior log probability of its value, and aggregates the
    shots by the reduction: ``logsumexp`` answers the log of the summed
    probabilities, the marginal; ``sum`` the sum of the weighted shots;
    ``mean`` their average. The aggregate is totalled over the plate's
    positions when the latent is plated, or kept one per position when
    a weight type is given, which is what a marginalization nested in a
    grouped one adds to its group's weights.

    Parameters
    ----------
    result_validator
        Checks the value a resumption carries inhabits the operation's
        result type.
    answer_type
        What the handled computation answers with.
    weight_type
        The type of the per-position weights the clause answers with,
        the collected weights' own tensor type, whose shape the answer
        takes from the shots' weights; ``None`` totals the positions
        into one ``LogWeight``.
    reduction
        How the shots aggregate: ``"logsumexp"``, ``"sum"``, or
        ``"mean"``.
    key
        Distinguishes this handler from others of the same name.

    Returns
    -------
    RuntimeHandler
        The attachment.

    Raises
    ------
    ValueError
        If the reduction is not one of the three.
    """
    if reduction not in ("logsumexp", "sum", "mean"):
        raise ValueError(
            f"enumeration reduces by logsumexp, sum, or mean, not {reduction!r}"
        )
    definition = _handler_def(
        "Random.enumerate",
        RANDOM,
        ((RANDOM_SAMPLE, ResumptionGrade.UNRESTRICTED),),
        key=key,
        input_type=answer_type,
        output_type=LOG_WEIGHT if weight_type is None else weight_type,
        telescope=_generic_binders(answer_type=answer_type),
    )
    per_position = weight_type is not None

    def sample(
        request: RuntimeRequest,
        resume: Resumption,
        _context: ClauseContext,
    ) -> object:
        """Answer a `Random.sample` request by enumeration.

        Parameters
        ----------
        request
            The request being answered and its arguments.
        resume
            The continuation, resumed once per support value.
        _context
            Runtime services, unused by this clause.

        Returns
        -------
        object
            The log of the marginal likelihood the scope accumulates, or
            the per-position marginals shaped by the weight type.

        Raises
        ------
        InvalidHandlerError
            If the request does not carry a site and a sampleable, the
            family has no finite support, a shot answers with something
            other than a value paired with its weight, or the shots'
            weights do not fill the weight type's positions.
        """
        _site, sampleable = _expect_arguments(request, 2, definition.name)
        support = _support(sampleable)
        distribution = cast(RuntimeDistribution, sampleable)
        prior_of = _hard_prior(distribution)
        shape = (*distribution.batch, *distribution.event)
        totals: list[list[float]] = []
        shapes: list[tuple[int, ...]] = []
        for choice in support:
            value = _reshape([choice] * math.prod(shape), shape) if shape else choice  # type: ignore[list-item]
            prior = prior_of.log_prob(_hard_atom(prior_of, value), keep_batch=True)
            answer = resume(value)
            if not isinstance(answer, tuple) or len(answer) != 2:
                raise InvalidHandlerError(
                    "enumeration expects each shot to answer with a value and "
                    "its accumulated weight"
                )
            weight = add_weights(prior, answer[1])
            totals.append(_entries(weight))
            shapes.append(_weight_shape(weight))
        width = max(len(entries) for entries in totals)
        marginals = [
            _aggregate([entries[position] for entries in totals], reduction)
            for position in range(width)
        ]
        if not per_position:
            return math.fsum(marginals)
        widest = max(shapes, key=len)
        if any(shape not in ((), widest) for shape in shapes):
            raise InvalidHandlerError(
                "enumeration answers per-position weights only when every "
                "shot's weights share one shape"
            )
        return _reshape(marginals, widest)

    return RuntimeHandler(
        definition,
        {RANDOM_SAMPLE: RuntimeClause(sample, result_validator)},
        duplicable_context=True,
    )

score_handler

score_handler(*, identity: object = 0.0, combine: Callable[[object, object], object] = _RUNTIME_ADD, weight_validator: RuntimeValidator = lambda _value: True, answer_validator: RuntimeValidator = lambda _value: True, total_validator: RuntimeValidator | None = None, expose_total: bool = False, answer_type: TypeExpr = ANSWER, key: str = 'score', observer: Callable[[RuntimeRequest, object], None] | None = None) -> tuple[RuntimeHandler, ScoreAccumulator]

Accumulate Score.add contributions in their evaluation order.

PARAMETER DESCRIPTION
identity

The accumulator's value before any contribution.

TYPE: object DEFAULT: 0.0

combine

Folds a contribution into the running total.

TYPE: Callable[[object, object], object] DEFAULT: _RUNTIME_ADD

weight_validator

Checks an individual weight contribution.

TYPE: RuntimeValidator DEFAULT: lambda _value: True

answer_validator

Checks the handled computation's answer.

TYPE: RuntimeValidator DEFAULT: lambda _value: True

total_validator

Checks the accumulated total; weight_validator when omitted.

TYPE: RuntimeValidator | None DEFAULT: None

expose_total

Whether the accumulated total is returned alongside the answer, rather than kept internal.

TYPE: bool DEFAULT: False

answer_type

What the handler answers with.

TYPE: TypeExpr DEFAULT: ANSWER

key

Distinguishes this handler from others of the same name, entering its derived identity.

TYPE: str DEFAULT: 'score'

observer

Called with each request and its contribution as it is accumulated, so a caller can attribute contributions to the sites their provenance names.

TYPE: Callable[[RuntimeRequest, object], None] | None DEFAULT: None

RETURNS DESCRIPTION
tuple[RuntimeHandler, ScoreAccumulator]

The attachment, ready to bind into a runtime environment, and the accumulator each installation publishes into when its computation completes.

Source code in src/quivers/qiec/builtins.py
def score_handler(
    *,
    identity: object = 0.0,
    combine: Callable[[object, object], object] = _RUNTIME_ADD,
    weight_validator: RuntimeValidator = lambda _value: True,
    answer_validator: RuntimeValidator = lambda _value: True,
    total_validator: RuntimeValidator | None = None,
    expose_total: bool = False,
    answer_type: TypeExpr = ANSWER,
    key: str = "score",
    observer: Callable[[RuntimeRequest, object], None] | None = None,
) -> tuple[RuntimeHandler, ScoreAccumulator]:
    """Accumulate ``Score.add`` contributions in their evaluation order.

    Parameters
    ----------
    identity
        The accumulator's value before any contribution.
    combine
        Folds a contribution into the running total.
    weight_validator
        Checks an individual weight contribution.
    answer_validator
        Checks the handled computation's answer.
    total_validator
        Checks the accumulated total; ``weight_validator`` when omitted.
    expose_total
        Whether the accumulated total is returned alongside the
        answer, rather than kept internal.
    answer_type
        What the handler answers with.
    key
        Distinguishes this handler from others of the same name,
        entering its derived identity.
    observer
        Called with each request and its contribution as it is
        accumulated, so a caller can attribute contributions to the
        sites their provenance names.

    Returns
    -------
    tuple[RuntimeHandler, ScoreAccumulator]
        The attachment, ready to bind into a runtime environment, and
        the accumulator each installation publishes into when its
        computation completes.
    """
    accumulator = ScoreAccumulator(identity)
    checked_total = total_validator or weight_validator
    output_type = (
        TypeApplication(WEIGHTED_RESULT_CONSTRUCTOR, (answer_type, LOG_WEIGHT))
        if expose_total
        else answer_type
    )
    definition = _handler_def(
        "Score.accumulate",
        SCORE,
        ((SCORE_ADD, ResumptionGrade.LINEAR),),
        key=key,
        input_type=answer_type,
        output_type=output_type,
        telescope=_generic_binders(answer_type=answer_type),
    )

    def make_context() -> RuntimeHandler:
        """Build a fresh per-installation handler.

        Returns
        -------
        RuntimeHandler
            A handler with its own state, so two installations of this
            declaration do not share it.
        """
        local = ScoreAccumulator(identity)

        def add(
            request: RuntimeRequest,
            resume: Resumption,
            _context: ClauseContext,
        ) -> object:
            """Answer a `Score.add` request by accumulating the weight.

            Parameters
            ----------
            request
                The request being answered and its arguments.
            resume
                The continuation, invoked within the clause's declared grade.
            _context
                Runtime services, unused by this clause.

            Returns
            -------
            object
                What the resumed computation produced.

            Raises
            ------
            InvalidHandlerError
                If the request does not carry exactly one argument.
            RuntimeTypeMismatch
                If the contribution does not inhabit the weight type.
            """
            (weight,) = _expect_arguments(request, 1, definition.name)
            _require(weight, weight_validator, LOG_WEIGHT, "score contribution")
            local.contributions.append(weight)
            local.total = combine(local.total, weight)
            if observer is not None:
                observer(request, weight)
            return TailResume(None)

        def finish(value: object, _context: ClauseContext) -> object:
            """Answer the handled computation's return.

            Parameters
            ----------
            value
                The value the handled computation returned.
            _context
                Runtime services, unused by this clause.

            Returns
            -------
            object
                The value paired with the accumulated total when
                ``expose_total`` is set, else the value alone.
            """
            return (value, local.total) if expose_total else value

        def publish() -> None:
            """Copy this installation's total and contributions to the accumulator."""
            accumulator.total = local.total
            accumulator.contributions[:] = local.contributions

        return RuntimeHandler(
            definition,
            {SCORE_ADD: RuntimeClause(add, _unit)},
            return_clause=finish,
            input_validator=answer_validator,
            output_validator=(
                _pair_of(answer_validator, checked_total)
                if expose_total
                else answer_validator
            ),
            mutable_context=True,
            on_exit=publish,
        )

    prototype = make_context()
    prototype.context_factory = make_context
    return prototype, accumulator

condition_handler

condition_handler(observations: Mapping[object, object], *, score_instance: EffectInstanceId, result_validator: RuntimeValidator, weight_validator: RuntimeValidator = lambda _value: True, missing: MissingValuePolicy = FORWARD, extra: ExtraValuePolicy = ERROR, answer_type: TypeExpr = ANSWER, key: str = 'condition') -> RuntimeHandler

Supply likelihood observations and emit their densities as Score.

Unobserved sites forward to the next Random handler. The explicit introduced Score row distinguishes likelihood observation from intervention and unscored replay.

PARAMETER DESCRIPTION
observations

The values to condition on, keyed by site.

TYPE: Mapping[object, object]

score_instance

The lexical Score instance each observation's log density is sent to.

TYPE: EffectInstanceId

result_validator

Checks an observed value inhabits the request's result type.

TYPE: RuntimeValidator

weight_validator

Checks each log-density contribution.

TYPE: RuntimeValidator DEFAULT: lambda _value: True

missing

Whether a sample request at a site with no observation is forwarded outward or rejected.

TYPE: MissingValuePolicy DEFAULT: FORWARD

extra

What to do, when the handled computation returns, with an observation at a site the computation never sampled.

TYPE: ExtraValuePolicy DEFAULT: ERROR

answer_type

What the handler answers with.

TYPE: TypeExpr DEFAULT: ANSWER

key

Distinguishes this handler from others of the same name, entering its derived identity.

TYPE: str DEFAULT: 'condition'

RETURNS DESCRIPTION
RuntimeHandler

The attachment, ready to bind into a runtime environment.

Source code in src/quivers/qiec/builtins.py
def condition_handler(
    observations: Mapping[object, object],
    *,
    score_instance: EffectInstanceId,
    result_validator: RuntimeValidator,
    weight_validator: RuntimeValidator = lambda _value: True,
    missing: MissingValuePolicy = MissingValuePolicy.FORWARD,
    extra: ExtraValuePolicy = ExtraValuePolicy.ERROR,
    answer_type: TypeExpr = ANSWER,
    key: str = "condition",
) -> RuntimeHandler:
    """Supply likelihood observations and emit their densities as Score.

    Unobserved sites forward to the next ``Random`` handler.  The explicit
    introduced Score row distinguishes likelihood observation from intervention
    and unscored replay.

    Parameters
    ----------
    observations
        The values to condition on, keyed by site.
    score_instance
        The lexical `Score` instance each observation's log density is
        sent to.
    result_validator
        Checks an observed value inhabits the request's result type.
    weight_validator
        Checks each log-density contribution.
    missing
        Whether a sample request at a site with no observation is
        forwarded outward or rejected.
    extra
        What to do, when the handled computation returns, with an
        observation at a site the computation never sampled.
    answer_type
        What the handler answers with.
    key
        Distinguishes this handler from others of the same name,
        entering its derived identity.

    Returns
    -------
    RuntimeHandler
        The attachment, ready to bind into a runtime environment.
    """
    definition = _handler_def(
        "Random.condition",
        RANDOM,
        ((RANDOM_SAMPLE, ResumptionGrade.LINEAR),),
        key=key,
        input_type=answer_type,
        output_type=answer_type,
        introduced=EffectRow((RowEntry(score_instance, SCORE),)),
        total=False,
        telescope=_generic_binders(answer_type=answer_type),
    )

    def make_context() -> RuntimeHandler:
        """Build a fresh per-installation handler.

        Returns
        -------
        RuntimeHandler
            A handler with its own state, so two installations of this
            declaration do not share it.
        """
        seen: set[object] = set()

        def sample(
            request: RuntimeRequest,
            resume: Resumption,
            context: ClauseContext,
        ) -> object:
            """Answer a `Random.sample` request.

            Parameters
            ----------
            request
                The request being answered and its arguments.
            resume
                The continuation, invoked within the clause's declared grade.
            context
                Runtime services available to the clause.

            Returns
            -------
            object
                What the resumed computation produced, or a `Forward` when
                the site has no observation and ``missing`` forwards.

            Raises
            ------
            InvalidHandlerError
                If the request's site has no observation and ``missing``
                rejects, or the request does not carry a site and a
                sampleable.
            RuntimeTypeMismatch
                If the observed value does not inhabit the site's type.
            """
            site, sampleable = _site_and_sampleable(request, definition.name)
            if site not in observations:
                if missing is MissingValuePolicy.ERROR:
                    raise InvalidHandlerError(f"missing observation for site {site!r}")
                return Forward()
            value = observations[site]
            _require(
                value,
                result_validator,
                request.core.result_type,
                f"observation {site!r}",
            )
            seen.add(site)
            weight = _log_density(sampleable, value)
            _emit_score(
                context,
                request,
                score_instance,
                weight,
                weight_validator,
                role="condition-score",
            )
            return TailResume(value)

        def finish(value: object, _context: ClauseContext) -> object:
            """Answer the handled computation's return.

            Parameters
            ----------
            value
                The value the handled computation returned.
            _context
                Runtime services, unused by this clause.

            Returns
            -------
            object
                The value, unchanged.

            Raises
            ------
            InvalidHandlerError
                If observations were supplied for sites the computation never
                sampled. Reported rather than ignored, since an unused
                observation usually means a site was renamed.
            """
            if extra is ExtraValuePolicy.ERROR:
                extras = set(observations) - seen
                if extras:
                    rendered = ", ".join(
                        repr(item) for item in sorted(extras, key=repr)
                    )
                    raise InvalidHandlerError(f"unused observations: {rendered}")
            return value

        return RuntimeHandler(
            definition,
            {RANDOM_SAMPLE: RuntimeClause(sample, result_validator)},
            return_clause=finish,
            mutable_context=True,
        )

    prototype = make_context()
    prototype.context_factory = make_context
    return prototype

replay_handler

replay_handler(values: Mapping[object, object], *, result_validator: RuntimeValidator, policy: ReplayPolicy = CLAMP_NO_SCORE, score_instance: EffectInstanceId | None = None, weight_validator: RuntimeValidator = lambda _value: True, extra: ExtraValuePolicy = ERROR, answer_type: TypeExpr = ANSWER, key: str = 'replay') -> RuntimeHandler

Replay selected sites under an explicit scoring/intervention policy.

A sample request at a site in values resumes with the recorded value; a request at any other site is forwarded to an outer handler. A site reached more than once, as a recurrence reaches the sites of its step at every position, replays the value keyed "<site>@<n>" at its n-th occurrence, counted from zero, when one is recorded, and the value keyed by the site alone otherwise.

PARAMETER DESCRIPTION
values

The recorded value for each replayed site, keyed by site, or by site and occurrence as "<site>@<n>".

TYPE: Mapping[object, object]

result_validator

Checks a replayed value inhabits the request's result type.

TYPE: RuntimeValidator

policy

Whether a replayed value is also scored: CLAMP_AND_SCORE sends its log density to score_instance, while CLAMP_NO_SCORE and INTERVENE replay it without scoring.

TYPE: ReplayPolicy DEFAULT: CLAMP_NO_SCORE

score_instance

The lexical Score instance replayed densities are sent to; required under CLAMP_AND_SCORE.

TYPE: EffectInstanceId | None DEFAULT: None

weight_validator

Checks each log-density contribution.

TYPE: RuntimeValidator DEFAULT: lambda _value: True

extra

What to do, when the handled computation returns, with a recorded site the computation never sampled.

TYPE: ExtraValuePolicy DEFAULT: ERROR

answer_type

What the handler answers with.

TYPE: TypeExpr DEFAULT: ANSWER

key

Distinguishes this handler from others of the same name, entering its derived identity.

TYPE: str DEFAULT: 'replay'

RETURNS DESCRIPTION
RuntimeHandler

The attachment, ready to bind into a runtime environment.

RAISES DESCRIPTION
ValueError

If policy is CLAMP_AND_SCORE and no score_instance is given.

Source code in src/quivers/qiec/builtins.py
def replay_handler(
    values: Mapping[object, object],
    *,
    result_validator: RuntimeValidator,
    policy: ReplayPolicy = ReplayPolicy.CLAMP_NO_SCORE,
    score_instance: EffectInstanceId | None = None,
    weight_validator: RuntimeValidator = lambda _value: True,
    extra: ExtraValuePolicy = ExtraValuePolicy.ERROR,
    answer_type: TypeExpr = ANSWER,
    key: str = "replay",
) -> RuntimeHandler:
    """Replay selected sites under an explicit scoring/intervention policy.

    A sample request at a site in ``values`` resumes with the recorded
    value; a request at any other site is forwarded to an outer handler.
    A site reached more than once, as a recurrence reaches the sites of
    its step at every position, replays the value keyed ``"<site>@<n>"``
    at its ``n``-th occurrence, counted from zero, when one is recorded,
    and the value keyed by the site alone otherwise.

    Parameters
    ----------
    values
        The recorded value for each replayed site, keyed by site, or by
        site and occurrence as ``"<site>@<n>"``.
    result_validator
        Checks a replayed value inhabits the request's result type.
    policy
        Whether a replayed value is also scored: ``CLAMP_AND_SCORE`` sends
        its log density to ``score_instance``, while ``CLAMP_NO_SCORE``
        and ``INTERVENE`` replay it without scoring.
    score_instance
        The lexical `Score` instance replayed densities are sent to;
        required under ``CLAMP_AND_SCORE``.
    weight_validator
        Checks each log-density contribution.
    extra
        What to do, when the handled computation returns, with a recorded
        site the computation never sampled.
    answer_type
        What the handler answers with.
    key
        Distinguishes this handler from others of the same name,
        entering its derived identity.

    Returns
    -------
    RuntimeHandler
        The attachment, ready to bind into a runtime environment.

    Raises
    ------
    ValueError
        If ``policy`` is ``CLAMP_AND_SCORE`` and no ``score_instance`` is
        given.
    """
    if policy is ReplayPolicy.CLAMP_AND_SCORE and score_instance is None:
        raise ValueError("scored replay requires a Score effect instance")
    introduced = (
        EffectRow((RowEntry(score_instance, SCORE),))
        if score_instance is not None and policy is ReplayPolicy.CLAMP_AND_SCORE
        else EffectRow()
    )
    definition = _handler_def(
        f"Random.replay.{policy.value}",
        RANDOM,
        ((RANDOM_SAMPLE, ResumptionGrade.LINEAR),),
        key=key,
        input_type=answer_type,
        output_type=answer_type,
        introduced=introduced,
        total=False,
        telescope=_generic_binders(answer_type=answer_type),
    )

    def make_context() -> RuntimeHandler:
        """Build a fresh per-installation handler.

        Returns
        -------
        RuntimeHandler
            A handler with its own state, so two installations of this
            declaration do not share it.
        """
        seen: set[object] = set()
        occurrences: dict[object, int] = {}

        def sample(
            request: RuntimeRequest,
            resume: Resumption,
            context: ClauseContext,
        ) -> object:
            """Answer a `Random.sample` request.

            Parameters
            ----------
            request
                The request being answered and its arguments.
            resume
                The continuation, invoked within the clause's declared grade.
            context
                Runtime services available to the clause.

            Returns
            -------
            object
                What the resumed computation produced, or a `Forward` when
                the site has no recorded value.

            Raises
            ------
            InvalidHandlerError
                If the request does not carry a site and a sampleable, or
                the value is scored and the sampleable has no ``log_prob``.
            RuntimeTypeMismatch
                If the recorded value does not inhabit the site's type.
            """
            site, sampleable = _site_and_sampleable(request, definition.name)
            occurrence = occurrences.get(site, 0)
            occurrences[site] = occurrence + 1
            key_at = f"{site}@{occurrence}"
            if key_at in values:
                site_key: object = key_at
            elif site in values:
                site_key = site
            else:
                return Forward()
            value = values[site_key]
            _require(
                value,
                result_validator,
                request.core.result_type,
                f"replay {site!r}",
            )
            seen.add(site_key)
            if policy is ReplayPolicy.CLAMP_AND_SCORE:
                assert score_instance is not None
                _emit_score(
                    context,
                    request,
                    score_instance,
                    _log_density(sampleable, value),
                    weight_validator,
                    role="replay-score",
                )
            return TailResume(value)

        def finish(value: object, _context: ClauseContext) -> object:
            """Answer the handled computation's return.

            Parameters
            ----------
            value
                The value the handled computation returned.
            _context
                Runtime services, unused by this clause.

            Returns
            -------
            object
                The value, unchanged.

            Raises
            ------
            InvalidHandlerError
                If recorded values remain unconsumed and the policy forbids it.
            """
            if extra is ExtraValuePolicy.ERROR:
                extras = set(values) - seen
                if extras:
                    rendered = ", ".join(
                        repr(item) for item in sorted(extras, key=repr)
                    )
                    raise InvalidHandlerError(f"unused replay values: {rendered}")
            return value

        return RuntimeHandler(
            definition,
            {RANDOM_SAMPLE: RuntimeClause(sample, result_validator)},
            return_clause=finish,
            mutable_context=True,
        )

    prototype = make_context()
    prototype.context_factory = make_context
    return prototype

trace_handler

trace_handler(effect: EffectRef, operations: Iterable[OperationId], recorder: TraceRecorder, *, validators: Mapping[OperationId, RuntimeValidator], answer_type: TypeExpr = ANSWER, key: str = 'trace') -> RuntimeHandler

Observe forwarded operation replies without interpreting the effect.

PARAMETER DESCRIPTION
effect

The interface whose operations are recorded.

TYPE: EffectRef

operations

Which operations to record.

TYPE: Iterable[OperationId]

recorder

Receives each recorded request.

TYPE: TraceRecorder

validators

Per-operation result validators.

TYPE: Mapping[OperationId, RuntimeValidator]

answer_type

What the handler answers with.

TYPE: TypeExpr DEFAULT: ANSWER

key

Distinguishes this handler from others of the same name, entering its derived identity.

TYPE: str DEFAULT: 'trace'

RETURNS DESCRIPTION
RuntimeHandler

The attachment, ready to bind into a runtime environment.

Source code in src/quivers/qiec/builtins.py
def trace_handler(
    effect: EffectRef,
    operations: Iterable[OperationId],
    recorder: TraceRecorder,
    *,
    validators: Mapping[OperationId, RuntimeValidator],
    answer_type: TypeExpr = ANSWER,
    key: str = "trace",
) -> RuntimeHandler:
    """Observe forwarded operation replies without interpreting the effect.

    Parameters
    ----------
    effect
        The interface whose operations are recorded.
    operations
        Which operations to record.
    recorder
        Receives each recorded request.
    validators
        Per-operation result validators.
    answer_type
        What the handler answers with.
    key
        Distinguishes this handler from others of the same name,
        entering its derived identity.

    Returns
    -------
    RuntimeHandler
        The attachment, ready to bind into a runtime environment.
    """
    operation_tuple = tuple(operations)
    definition = _handler_def(
        f"{effect.name}.trace",
        effect,
        tuple((operation, ResumptionGrade.AFFINE) for operation in operation_tuple),
        key=key,
        input_type=answer_type,
        output_type=answer_type,
        total=False,
        telescope=_generic_binders(answer_type=answer_type),
    )

    def make_clause(operation: OperationId):
        """Build the clause implementing one operation.

        Parameters
        ----------
        operation
            The operation this clause is being built for.

        Returns
        -------
        RuntimeClause
            The clause and its result validator.

        Raises
        ------
        ValueError
            If the operation has no validator among those supplied.
        """

        def clause(
            request: RuntimeRequest,
            _resume: Resumption,
            _context: ClauseContext,
        ) -> object:
            """Answer the request this clause covers.

            Parameters
            ----------
            request
                The request being answered and its arguments.
            _resume
                The continuation, which this clause does not invoke.
            _context
                Runtime services, unused by this clause.

            Returns
            -------
            object
                A `Forward` whose response hook records the outer
                handler's reply.
            """
            return Forward(
                lambda result: recorder.record(request, result, mode="forwarded")
            )

        try:
            validator = validators[operation]
        except KeyError as error:
            raise ValueError(
                f"trace handler needs a validator for {operation}"
            ) from error

        def checked_clause(
            request: RuntimeRequest,
            resume: Resumption,
            context: ClauseContext,
        ) -> object:
            """Answer the request, validating the resumed value.

            Parameters
            ----------
            request
                The request being answered and its arguments.
            resume
                The continuation, invoked within the clause's declared grade.
            context
                Runtime services available to the clause.

            Returns
            -------
            object
                A `Forward` whose response hook validates the outer
                handler's reply before recording it.
            """
            answer = clause(request, resume, context)
            assert isinstance(answer, Forward)
            hook = answer.on_response

            def validate_and_record(result: object) -> object:
                """Check a produced value and record it.

                Parameters
                ----------
                result
                    The value produced for the request.

                Returns
                -------
                object
                    The value, unchanged, so the caller can use this in
                    place of what it passed.

                Raises
                ------
                RuntimeTypeMismatch
                    If the value does not inhabit the operation's result
                    type.
                """
                _require(
                    result,
                    validator,
                    request.core.result_type,
                    f"traced result of {request.operation}",
                )
                assert hook is not None
                return hook(result)

            return Forward(validate_and_record)

        return RuntimeClause(checked_clause, validator)

    return RuntimeHandler(
        definition,
        {operation: make_clause(operation) for operation in operation_tuple},
    )

state_handler

state_handler(initial: object, state_validator: RuntimeValidator, *, state_type: TypeExpr = STATE, expose_final: bool = False, answer_type: TypeExpr = ANSWER, answer_validator: RuntimeValidator = lambda _value: True, key: str = 'state') -> tuple[RuntimeHandler, StateCell]

Interpret lexical State.get/put with a nonduplicable mutable cell.

PARAMETER DESCRIPTION
initial

The state before any operation.

TYPE: object

state_validator

Checks the initial state, each value put, and each value got.

TYPE: RuntimeValidator

state_type

The type of the handler's state.

TYPE: TypeExpr DEFAULT: STATE

expose_final

Whether the final state is returned alongside the answer.

TYPE: bool DEFAULT: False

answer_type

What the handler answers with.

TYPE: TypeExpr DEFAULT: ANSWER

answer_validator

Checks the handled computation's answer.

TYPE: RuntimeValidator DEFAULT: lambda _value: True

key

Distinguishes this handler from others of the same name, entering its derived identity.

TYPE: str DEFAULT: 'state'

RETURNS DESCRIPTION
tuple[RuntimeHandler, StateCell]

The attachment, ready to bind into a runtime environment, and the cell each installation publishes its final state into when its computation completes.

RAISES DESCRIPTION
RuntimeTypeMismatch

If initial does not inhabit state_type.

Source code in src/quivers/qiec/builtins.py
def state_handler(
    initial: object,
    state_validator: RuntimeValidator,
    *,
    state_type: TypeExpr = STATE,
    expose_final: bool = False,
    answer_type: TypeExpr = ANSWER,
    answer_validator: RuntimeValidator = lambda _value: True,
    key: str = "state",
) -> tuple[RuntimeHandler, StateCell]:
    """Interpret lexical State.get/put with a nonduplicable mutable cell.

    Parameters
    ----------
    initial
        The state before any operation.
    state_validator
        Checks the initial state, each value put, and each value got.
    state_type
        The type of the handler's state.
    expose_final
        Whether the final state is returned alongside the answer.
    answer_type
        What the handler answers with.
    answer_validator
        Checks the handled computation's answer.
    key
        Distinguishes this handler from others of the same name,
        entering its derived identity.

    Returns
    -------
    tuple[RuntimeHandler, StateCell]
        The attachment, ready to bind into a runtime environment, and
        the cell each installation publishes its final state into when
        its computation completes.

    Raises
    ------
    RuntimeTypeMismatch
        If ``initial`` does not inhabit ``state_type``.
    """
    _require(initial, state_validator, state_type, "initial state")
    cell = StateCell(initial)
    effect = state_effect(state_type)
    definition = _handler_def(
        "State.run",
        effect,
        (
            (STATE_GET, ResumptionGrade.LINEAR),
            (STATE_PUT, ResumptionGrade.LINEAR),
        ),
        key=key,
        input_type=answer_type,
        output_type=(
            TypeApplication(STATE_RESULT_CONSTRUCTOR, (answer_type, state_type))
            if expose_final
            else answer_type
        ),
        telescope=_generic_binders(
            answer_type=answer_type,
            state_type=state_type,
        ),
    )

    def make_context() -> RuntimeHandler:
        """Build a fresh per-installation handler.

        Returns
        -------
        RuntimeHandler
            A handler with its own state, so two installations of this
            declaration do not share it.
        """
        local = StateCell(initial)

        def get(
            request: RuntimeRequest,
            resume: Resumption,
            _context: ClauseContext,
        ) -> object:
            """Answer a `State.get` request with the current state.

            Parameters
            ----------
            request
                The request being answered and its arguments.
            resume
                The continuation, invoked within the clause's declared grade.
            _context
                Runtime services, unused by this clause.

            Returns
            -------
            object
                What the resumed computation produced.

            Raises
            ------
            InvalidHandlerError
                If the request carries any argument.
            """
            _expect_arguments(request, 0, definition.name)
            return TailResume(local.value)

        def put(
            request: RuntimeRequest,
            resume: Resumption,
            _context: ClauseContext,
        ) -> object:
            """Answer a `State.put` request by replacing the state.

            Parameters
            ----------
            request
                The request being answered and its arguments.
            resume
                The continuation, invoked within the clause's declared grade.
            _context
                Runtime services, unused by this clause.

            Returns
            -------
            object
                What the resumed computation produced.

            Raises
            ------
            InvalidHandlerError
                If the request does not carry exactly one argument.
            RuntimeTypeMismatch
                If the new state does not inhabit ``state_type``.
            """
            (new_value,) = _expect_arguments(request, 1, definition.name)
            _require(new_value, state_validator, state_type, "state update")
            local.value = new_value
            return TailResume(None)

        def finish(value: object, _context: ClauseContext) -> object:
            """Answer the handled computation's return.

            Parameters
            ----------
            value
                The value the handled computation returned.
            _context
                Runtime services, unused by this clause.

            Returns
            -------
            object
                The value paired with the final state when
                ``expose_final`` is set, else the value alone.
            """
            return (value, local.value) if expose_final else value

        def publish() -> None:
            """Copy this installation's final state to the shared cell."""
            cell.value = local.value

        return RuntimeHandler(
            definition,
            {
                STATE_GET: RuntimeClause(get, state_validator),
                STATE_PUT: RuntimeClause(put, _unit),
            },
            return_clause=finish,
            input_validator=answer_validator,
            output_validator=(
                _pair_of(answer_validator, state_validator)
                if expose_final
                else answer_validator
            ),
            mutable_context=True,
            on_exit=publish,
        )

    prototype = make_context()
    prototype.context_factory = make_context
    return prototype, cell

abort_handler

abort_handler(*, on_abort: Callable[[object], object] = Aborted, result_validator: RuntimeValidator = lambda _value: True, error_type: TypeExpr = PAYLOAD, input_type: TypeExpr = ANSWER, output_type: TypeExpr = ANSWER, output_validator: RuntimeValidator = lambda _value: True, duplicable_context: bool = False, key: str = 'abort') -> RuntimeHandler

Handle Abort.abort without resuming the discarded continuation.

PARAMETER DESCRIPTION
on_abort

Receives the payload when the computation aborts and supplies the handler's answer; wraps it in Aborted by default.

TYPE: Callable[[object], object] DEFAULT: Aborted

result_validator

The abort operation's result validator; never exercised, since the clause does not resume.

TYPE: RuntimeValidator DEFAULT: lambda _value: True

error_type

The payload type an abort carries.

TYPE: TypeExpr DEFAULT: PAYLOAD

input_type

What the handled computation returns.

TYPE: TypeExpr DEFAULT: ANSWER

output_type

What the handler answers with.

TYPE: TypeExpr DEFAULT: ANSWER

output_validator

Checks the handler's answer.

TYPE: RuntimeValidator DEFAULT: lambda _value: True

duplicable_context

Whether the handler's own state may be copied for a multi-shot resumption. Asserted rather than inferred: copying a handler owning mutable state would let two shots share it.

TYPE: bool DEFAULT: False

key

Distinguishes this handler from others of the same name, entering its derived identity.

TYPE: str DEFAULT: 'abort'

RETURNS DESCRIPTION
RuntimeHandler

The attachment, ready to bind into a runtime environment.

Source code in src/quivers/qiec/builtins.py
def abort_handler(
    *,
    on_abort: Callable[[object], object] = Aborted,
    result_validator: RuntimeValidator = lambda _value: True,
    error_type: TypeExpr = PAYLOAD,
    input_type: TypeExpr = ANSWER,
    output_type: TypeExpr = ANSWER,
    output_validator: RuntimeValidator = lambda _value: True,
    duplicable_context: bool = False,
    key: str = "abort",
) -> RuntimeHandler:
    """Handle Abort.abort without resuming the discarded continuation.

    Parameters
    ----------
    on_abort
        Receives the payload when the computation aborts and supplies
        the handler's answer; wraps it in `Aborted` by default.
    result_validator
        The abort operation's result validator; never exercised, since
        the clause does not resume.
    error_type
        The payload type an abort carries.
    input_type
        What the handled computation returns.
    output_type
        What the handler answers with.
    output_validator
        Checks the handler's answer.
    duplicable_context
        Whether the handler's own state may be copied for a
        multi-shot resumption. Asserted rather than inferred: copying a
        handler owning mutable state would let two shots share it.
    key
        Distinguishes this handler from others of the same name,
        entering its derived identity.

    Returns
    -------
    RuntimeHandler
        The attachment, ready to bind into a runtime environment.
    """
    effect = abort_effect(error_type)
    definition = _handler_def(
        "Abort.run",
        effect,
        ((ABORT_ABORT, ResumptionGrade.ZERO),),
        key=key,
        input_type=input_type,
        output_type=output_type,
        telescope=tuple(
            dict.fromkeys(
                (
                    *_generic_binders(answer_type=input_type),
                    *_generic_binders(answer_type=output_type),
                    *_generic_binders(error_type=error_type),
                )
            )
        ),
    )

    def abort(
        request: RuntimeRequest,
        _resume: Resumption,
        _context: ClauseContext,
    ) -> object:
        """Answer an abort request without resuming.

        Parameters
        ----------
        request
            The request being answered and its arguments.
        _resume
            The continuation, which this clause does not invoke.
        _context
            Runtime services, unused by this clause.

        Returns
        -------
        object
            What ``on_abort`` makes of the payload; the continuation is
            discarded.

        Raises
        ------
        InvalidHandlerError
            If the request does not carry exactly one argument.
        """
        (error,) = _expect_arguments(request, 1, definition.name)
        return on_abort(error)

    return RuntimeHandler(
        definition,
        {ABORT_ABORT: RuntimeClause(abort, result_validator)},
        output_validator=output_validator,
        duplicable_context=duplicable_context,
    )

choose_handler

choose_handler(choice_validator: RuntimeValidator, *, combine: Callable[[list[object]], object] | None = None, combine_validator: RuntimeValidator | None = None, answer_type: TypeExpr = ANSWER, answer_validator: RuntimeValidator = lambda _value: True, key: str = 'choose') -> RuntimeHandler

Enumerate finite choices using an unrestricted deep resumption.

PARAMETER DESCRIPTION
choice_validator

Checks each alternative resumed with.

TYPE: RuntimeValidator

combine

Folds the per-alternative results into the handler's answer; None concatenates them, the return clause having wrapped each answer in a one-element tuple.

TYPE: Callable[[list[object]], object] | None DEFAULT: None

combine_validator

Checks the combined answer; required with a custom combine, and otherwise a tuple of answer_validator values.

TYPE: RuntimeValidator | None DEFAULT: None

answer_type

What the handled computation returns; the handler answers with ChoiceResults of it.

TYPE: TypeExpr DEFAULT: ANSWER

answer_validator

Checks the handled computation's answer.

TYPE: RuntimeValidator DEFAULT: lambda _value: True

key

Distinguishes this handler from others of the same name, entering its derived identity.

TYPE: str DEFAULT: 'choose'

RETURNS DESCRIPTION
RuntimeHandler

The attachment, ready to bind into a runtime environment.

RAISES DESCRIPTION
ValueError

If combine is given without combine_validator.

Source code in src/quivers/qiec/builtins.py
def choose_handler(
    choice_validator: RuntimeValidator,
    *,
    combine: Callable[[list[object]], object] | None = None,
    combine_validator: RuntimeValidator | None = None,
    answer_type: TypeExpr = ANSWER,
    answer_validator: RuntimeValidator = lambda _value: True,
    key: str = "choose",
) -> RuntimeHandler:
    """Enumerate finite choices using an unrestricted deep resumption.

    Parameters
    ----------
    choice_validator
        Checks each alternative resumed with.
    combine
        Folds the per-alternative results into the handler's answer;
        ``None`` concatenates them, the return clause having wrapped each
        answer in a one-element tuple.
    combine_validator
        Checks the combined answer; required with a custom ``combine``,
        and otherwise a tuple of ``answer_validator`` values.
    answer_type
        What the handled computation returns; the handler answers with
        ``ChoiceResults`` of it.
    answer_validator
        Checks the handled computation's answer.
    key
        Distinguishes this handler from others of the same name,
        entering its derived identity.

    Returns
    -------
    RuntimeHandler
        The attachment, ready to bind into a runtime environment.

    Raises
    ------
    ValueError
        If ``combine`` is given without ``combine_validator``.
    """
    if combine is not None and combine_validator is None:
        raise ValueError("a custom Choose combine needs an output validator")
    definition = _handler_def(
        "Choose.enumerate",
        CHOOSE,
        ((CHOOSE_CHOOSE, ResumptionGrade.UNRESTRICTED),),
        key=key,
        input_type=answer_type,
        output_type=TypeApplication(CHOICE_RESULTS_CONSTRUCTOR, (answer_type,)),
        telescope=_generic_binders(answer_type=answer_type),
    )

    def choose(
        request: RuntimeRequest,
        resume: Resumption,
        _context: ClauseContext,
    ) -> object:
        """Answer a choice request, resuming once per alternative.

        Parameters
        ----------
        request
            The request being answered and its arguments.
        resume
            The continuation, invoked within the clause's declared grade.
        _context
            Runtime services, unused by this clause.

        Returns
        -------
        object
            The combined result over every alternative.

        Raises
        ------
        InvalidHandlerError
            If the request does not carry exactly one argument, the
            alternatives are a string, bytes, or not iterable, or, under
            the default combination, the return clause's results are not
            tuples.
        """
        (alternatives,) = _expect_arguments(request, 1, definition.name)
        if isinstance(alternatives, (str, bytes)):
            raise InvalidHandlerError("Choose alternatives must be a finite collection")
        try:
            options = tuple(alternatives)  # type: ignore[arg-type]
        except TypeError as error:
            raise InvalidHandlerError("Choose alternatives must be iterable") from error
        results = [resume(option) for option in options]
        if combine is not None:
            return combine(results)
        flattened: list[object] = []
        for result in results:
            if not isinstance(result, tuple):
                raise InvalidHandlerError(
                    "the default Choose handler expects its deep return clause "
                    "to produce tuples"
                )
            flattened.extend(result)
        return tuple(flattened)

    return RuntimeHandler(
        definition,
        {CHOOSE_CHOOSE: RuntimeClause(choose, choice_validator)},
        return_clause=lambda value, _context: (value,),
        input_validator=answer_validator,
        output_validator=(
            combine_validator
            if combine_validator is not None
            else _tuple_of(answer_validator)
        ),
        duplicable_context=True,
    )

search_handler

search_handler(definition: HandlerDef, operation: OperationId, *, reduction: str, alternative_validator: RuntimeValidator) -> RuntimeHandler

Enumerate a tensor of alternatives, summing the shots' weights.

The handled computation answers with a unit paired with the weight a collecting handler inside it accumulated, which the return clause reduces to the weight. The clause resumes once per entry of the tensor it is asked to choose from and answers the semiring sum of what the resumptions answer, so an empty choice contributes the semiring's zero; a resumption's answer is itself a semiring sum when the continuation chooses again, and the sum is associative, so the nesting does not matter.

PARAMETER DESCRIPTION
definition

The module's declaration of the handler, whose one clause handles the choosing operation with an unrestricted resumption.

TYPE: HandlerDef

operation

The choosing operation.

TYPE: OperationId

reduction

The semiring addition, one of SEARCH_REDUCTIONS.

TYPE: str

alternative_validator

Checks the value each resumption carries.

TYPE: RuntimeValidator

RETURNS DESCRIPTION
RuntimeHandler

The attachment.

RAISES DESCRIPTION
ValueError

If the reduction is unknown.

Source code in src/quivers/qiec/builtins.py
def search_handler(
    definition: HandlerDef,
    operation: OperationId,
    *,
    reduction: str,
    alternative_validator: RuntimeValidator,
) -> RuntimeHandler:
    """Enumerate a tensor of alternatives, summing the shots' weights.

    The handled computation answers with a unit paired with the weight
    a collecting handler inside it accumulated, which the return clause
    reduces to the weight. The clause resumes once per entry of the
    tensor it is asked to choose from and answers the semiring sum of
    what the resumptions answer, so an empty choice contributes the
    semiring's zero; a resumption's answer is itself a semiring sum when
    the continuation chooses again, and the sum is associative, so the
    nesting does not matter.

    Parameters
    ----------
    definition
        The module's declaration of the handler, whose one clause
        handles the choosing operation with an unrestricted resumption.
    operation
        The choosing operation.
    reduction
        The semiring addition, one of ``SEARCH_REDUCTIONS``.
    alternative_validator
        Checks the value each resumption carries.

    Returns
    -------
    RuntimeHandler
        The attachment.

    Raises
    ------
    ValueError
        If the reduction is unknown.
    """
    if reduction not in SEARCH_REDUCTIONS:
        raise ValueError(
            f"a search combines its shots by one of {', '.join(SEARCH_REDUCTIONS)}, "
            f"not {reduction!r}"
        )

    def choose(
        request: RuntimeRequest,
        resume: Resumption,
        _context: ClauseContext,
    ) -> object:
        """Answer a choice by resuming once per alternative.

        Parameters
        ----------
        request
            The request being answered and its arguments.
        resume
            The continuation, resumed once per alternative.
        _context
            Runtime services, unused by this clause.

        Returns
        -------
        object
            The semiring sum of the shots' weights.

        Raises
        ------
        InvalidHandlerError
            If the request does not carry one tensor of alternatives.
        """
        (alternatives,) = _expect_arguments(request, 1, definition.name)
        if not isinstance(alternatives, tuple):
            raise InvalidHandlerError("a search chooses among the entries of a tensor")
        return _search_combine(
            reduction, [resume(alternative) for alternative in alternatives]
        )

    def finish(value: object, _context: ClauseContext) -> object:
        """Reduce the handled computation's answer to its weight.

        Parameters
        ----------
        value
            The value paired with its accumulated weight.
        _context
            Runtime services, unused by this clause.

        Returns
        -------
        object
            The weight.

        Raises
        ------
        InvalidHandlerError
            If the answer is not a value paired with its weight.
        """
        if not isinstance(value, tuple) or len(value) != 2:
            raise InvalidHandlerError(
                "a search expects the handled computation to answer with a value "
                "and its accumulated weight"
            )
        return value[1]

    return RuntimeHandler(
        definition,
        {operation: RuntimeClause(choose, alternative_validator)},
        return_clause=finish,
        duplicable_context=True,
    )

weight_handler

weight_handler(identity: object, combine: Callable[[object, object], object], weight_validator: RuntimeValidator, *, weight_type: TypeExpr = K, expose_total: bool = True, answer_type: TypeExpr = ANSWER, answer_validator: RuntimeValidator = lambda _value: True, total_validator: RuntimeValidator | None = None, forkable: bool = False, key: str = 'weight') -> tuple[RuntimeHandler, WeightAccumulator]

Accumulate values in a caller-supplied semiring multiplication.

PARAMETER DESCRIPTION
identity

The accumulator's value before any contribution.

TYPE: object

combine

Folds a contribution into the running total.

TYPE: Callable[[object, object], object]

weight_validator

Checks an individual weight contribution.

TYPE: RuntimeValidator

weight_type

The type of an individual weight.

TYPE: TypeExpr DEFAULT: K

expose_total

Whether the accumulated total is returned alongside the answer, rather than kept internal.

TYPE: bool DEFAULT: True

answer_type

What the handler answers with.

TYPE: TypeExpr DEFAULT: ANSWER

answer_validator

Checks the handled computation's answer.

TYPE: RuntimeValidator DEFAULT: lambda _value: True

total_validator

Checks the accumulated total; weight_validator when omitted.

TYPE: RuntimeValidator | None DEFAULT: None

forkable

Whether an unrestricted resumption may capture an installation: each shot then continues from its own copy of the total so far, which is what a search inside the scope needs.

TYPE: bool DEFAULT: False

key

Distinguishes this handler from others of the same name, entering its derived identity.

TYPE: str DEFAULT: 'weight'

RETURNS DESCRIPTION
tuple[RuntimeHandler, WeightAccumulator]

The attachment, ready to bind into a runtime environment, and the accumulator each installation publishes into when its computation completes.

Source code in src/quivers/qiec/builtins.py
def weight_handler(
    identity: object,
    combine: Callable[[object, object], object],
    weight_validator: RuntimeValidator,
    *,
    weight_type: TypeExpr = K,
    expose_total: bool = True,
    answer_type: TypeExpr = ANSWER,
    answer_validator: RuntimeValidator = lambda _value: True,
    total_validator: RuntimeValidator | None = None,
    forkable: bool = False,
    key: str = "weight",
) -> tuple[RuntimeHandler, WeightAccumulator]:
    """Accumulate values in a caller-supplied semiring multiplication.

    Parameters
    ----------
    identity
        The accumulator's value before any contribution.
    combine
        Folds a contribution into the running total.
    weight_validator
        Checks an individual weight contribution.
    weight_type
        The type of an individual weight.
    expose_total
        Whether the accumulated total is returned alongside the
        answer, rather than kept internal.
    answer_type
        What the handler answers with.
    answer_validator
        Checks the handled computation's answer.
    total_validator
        Checks the accumulated total; ``weight_validator`` when omitted.
    forkable
        Whether an unrestricted resumption may capture an installation:
        each shot then continues from its own copy of the total so far,
        which is what a search inside the scope needs.
    key
        Distinguishes this handler from others of the same name,
        entering its derived identity.

    Returns
    -------
    tuple[RuntimeHandler, WeightAccumulator]
        The attachment, ready to bind into a runtime environment, and
        the accumulator each installation publishes into when its
        computation completes.
    """
    accumulator = WeightAccumulator(identity)
    checked_total = total_validator or weight_validator
    effect = weight_effect(weight_type)
    definition = _handler_def(
        "Weight.accumulate",
        effect,
        ((WEIGHT_ADD, ResumptionGrade.LINEAR),),
        key=key,
        input_type=answer_type,
        output_type=(
            TypeApplication(WEIGHTED_RESULT_CONSTRUCTOR, (answer_type, weight_type))
            if expose_total
            else answer_type
        ),
        telescope=_generic_binders(
            answer_type=answer_type,
            weight_type=weight_type,
        ),
    )

    def make_context(seed: WeightAccumulator | None = None) -> RuntimeHandler:
        """Build a fresh per-installation handler.

        Parameters
        ----------
        seed : WeightAccumulator | None
            The state a fork continues from; ``None`` starts at the
            identity.

        Returns
        -------
        RuntimeHandler
            A handler with its own state, so two installations of this
            declaration do not share it.
        """
        local = (
            WeightAccumulator(identity)
            if seed is None
            else WeightAccumulator(seed.total, list(seed.contributions))
        )

        def add(
            request: RuntimeRequest,
            resume: Resumption,
            _context: ClauseContext,
        ) -> object:
            """Answer a `Score.add` request by accumulating the weight.

            Parameters
            ----------
            request
                The request being answered and its arguments.
            resume
                The continuation, invoked within the clause's declared grade.
            _context
                Runtime services, unused by this clause.

            Returns
            -------
            object
                A tail resumption with the unit answer, so the scope
                continues on the machine's stack and a search inside it
                may resume any number of times.

            Raises
            ------
            InvalidHandlerError
                If the request does not carry exactly one argument.
            RuntimeTypeMismatch
                If the contribution does not inhabit the weight type.
            """
            del resume
            (weight,) = _expect_arguments(request, 1, definition.name)
            _require(weight, weight_validator, weight_type, "semiring weight")
            local.contributions.append(weight)
            local.total = combine(local.total, weight)
            return TailResume(None)

        def finish(value: object, _context: ClauseContext) -> object:
            """Answer the handled computation's return.

            Parameters
            ----------
            value
                The value the handled computation returned.
            _context
                Runtime services, unused by this clause.

            Returns
            -------
            object
                The value paired with the accumulated total when
                ``expose_total`` is set, else the value alone.
            """
            return (value, local.total) if expose_total else value

        def publish() -> None:
            """Copy this installation's total and contributions to the accumulator."""
            accumulator.total = local.total
            accumulator.contributions[:] = local.contributions

        def fork(_handler: RuntimeHandler) -> RuntimeHandler:
            """Copy this installation for another shot.

            Parameters
            ----------
            _handler : RuntimeHandler
                The installation forked, which is this one.

            Returns
            -------
            RuntimeHandler
                An installation continuing from the same total.
            """
            return make_context(local)

        return RuntimeHandler(
            definition,
            {WEIGHT_ADD: RuntimeClause(add, _unit)},
            return_clause=finish,
            input_validator=answer_validator,
            output_validator=(
                _pair_of(answer_validator, checked_total)
                if expose_total
                else answer_validator
            ),
            mutable_context=True,
            duplicable_context=forkable,
            fork_context=fork if forkable else None,
            on_exit=publish,
        )

    prototype = make_context()
    prototype.context_factory = make_context
    return prototype, accumulator

draw_scoring_handler

draw_scoring_handler(*, score_instance: EffectInstanceId, result_validator: RuntimeValidator, weight_validator: RuntimeValidator = lambda _value: True, draw: Callable[[object, object, RuntimeRequest], object] | None = None, answer_type: TypeExpr = ANSWER, key: str = 'draw-scoring') -> RuntimeHandler

Interpret Random.sample by drawing once and scoring the draw.

The draw's log density under its own sampleable is sent to a Score instance, so a run whose latent sites are drawn accumulates the joint density of the draw, which is what a trace of the run reports.

PARAMETER DESCRIPTION
score_instance

The lexical Score instance each draw's log density is sent to.

TYPE: EffectInstanceId

result_validator

Checks the value a resumption carries inhabits the operation's result type.

TYPE: RuntimeValidator

weight_validator

Checks each log-density contribution.

TYPE: RuntimeValidator DEFAULT: lambda _value: True

draw

Supplies the drawn value, given the site, the sampleable, and the request. None uses the sampleable's own sampling interface.

TYPE: Callable[[object, object, RuntimeRequest], object] | None DEFAULT: None

answer_type

What the handler answers with.

TYPE: TypeExpr DEFAULT: ANSWER

key

Distinguishes this handler from others of the same name, entering its derived identity.

TYPE: str DEFAULT: 'draw-scoring'

RETURNS DESCRIPTION
RuntimeHandler

The attachment, ready to bind into a runtime environment.

Source code in src/quivers/qiec/builtins.py
def draw_scoring_handler(
    *,
    score_instance: EffectInstanceId,
    result_validator: RuntimeValidator,
    weight_validator: RuntimeValidator = lambda _value: True,
    draw: Callable[[object, object, RuntimeRequest], object] | None = None,
    answer_type: TypeExpr = ANSWER,
    key: str = "draw-scoring",
) -> RuntimeHandler:
    """Interpret ``Random.sample`` by drawing once and scoring the draw.

    The draw's log density under its own sampleable is sent to a `Score`
    instance, so a run whose latent sites are drawn accumulates the joint
    density of the draw, which is what a trace of the run reports.

    Parameters
    ----------
    score_instance
        The lexical `Score` instance each draw's log density is sent to.
    result_validator
        Checks the value a resumption carries inhabits the operation's
        result type.
    weight_validator
        Checks each log-density contribution.
    draw
        Supplies the drawn value, given the site, the sampleable, and
        the request. None uses the sampleable's own sampling interface.
    answer_type
        What the handler answers with.
    key
        Distinguishes this handler from others of the same name,
        entering its derived identity.

    Returns
    -------
    RuntimeHandler
        The attachment, ready to bind into a runtime environment.
    """
    definition = _handler_def(
        "Random.draw-scoring",
        RANDOM,
        ((RANDOM_SAMPLE, ResumptionGrade.LINEAR),),
        key=key,
        input_type=answer_type,
        output_type=answer_type,
        introduced=EffectRow((RowEntry(score_instance, SCORE),)),
        telescope=_generic_binders(answer_type=answer_type),
    )

    def sample(
        request: RuntimeRequest,
        resume: Resumption,
        context: ClauseContext,
    ) -> object:
        """Answer a `Random.sample` request by drawing and scoring.

        Parameters
        ----------
        request
            The request being answered and its arguments.
        resume
            The continuation, invoked within the clause's declared grade.
        context
            Runtime services available to the clause.

        Returns
        -------
        object
            What the resumed computation produced.

        Raises
        ------
        InvalidHandlerError
            If the request does not carry a site and a sampleable, or the
            sampleable offers no sampling or scoring interface.
        """
        site, sampleable = _site_and_sampleable(request, definition.name)
        value = (
            draw(site, sampleable, request)
            if draw is not None
            else _default_draw(sampleable)
        )
        _emit_score(
            context,
            request,
            score_instance,
            _log_density(sampleable, value),
            weight_validator,
            role="draw-score",
        )
        return TailResume(value)

    return RuntimeHandler(
        definition,
        {RANDOM_SAMPLE: RuntimeClause(sample, result_validator)},
    )

intervene_handler

intervene_handler(values: Mapping[object, object], *, result_validator: RuntimeValidator, on_intervene: Callable[[RuntimeRequest, object], None] | None = None, answer_type: TypeExpr = ANSWER, key: str = 'intervene') -> RuntimeHandler

Fix selected sites to given values without scoring them.

An intervened site's distribution is replaced by a point mass, so it contributes nothing to the joint; sites without a value forward.

PARAMETER DESCRIPTION
values

The value for each intervened site, keyed by site.

TYPE: Mapping[object, object]

result_validator

Checks an intervened value inhabits the request's result type.

TYPE: RuntimeValidator

on_intervene

Called with the request and the value fixed for it, so a caller can mark the site as deterministic.

TYPE: Callable[[RuntimeRequest, object], None] | None DEFAULT: None

answer_type

What the handler answers with.

TYPE: TypeExpr DEFAULT: ANSWER

key

Distinguishes this handler from others of the same name, entering its derived identity.

TYPE: str DEFAULT: 'intervene'

RETURNS DESCRIPTION
RuntimeHandler

The attachment, ready to bind into a runtime environment.

Source code in src/quivers/qiec/builtins.py
def intervene_handler(
    values: Mapping[object, object],
    *,
    result_validator: RuntimeValidator,
    on_intervene: Callable[[RuntimeRequest, object], None] | None = None,
    answer_type: TypeExpr = ANSWER,
    key: str = "intervene",
) -> RuntimeHandler:
    """Fix selected sites to given values without scoring them.

    An intervened site's distribution is replaced by a point mass, so it
    contributes nothing to the joint; sites without a value forward.

    Parameters
    ----------
    values
        The value for each intervened site, keyed by site.
    result_validator
        Checks an intervened value inhabits the request's result type.
    on_intervene
        Called with the request and the value fixed for it, so a caller
        can mark the site as deterministic.
    answer_type
        What the handler answers with.
    key
        Distinguishes this handler from others of the same name,
        entering its derived identity.

    Returns
    -------
    RuntimeHandler
        The attachment, ready to bind into a runtime environment.
    """
    definition = _handler_def(
        "Random.intervene",
        RANDOM,
        ((RANDOM_SAMPLE, ResumptionGrade.LINEAR),),
        key=key,
        input_type=answer_type,
        output_type=answer_type,
        total=False,
        telescope=_generic_binders(answer_type=answer_type),
    )

    def sample(
        request: RuntimeRequest,
        resume: Resumption,
        _context: ClauseContext,
    ) -> object:
        """Answer a `Random.sample` request with the intervened value.

        Parameters
        ----------
        request
            The request being answered and its arguments.
        resume
            The continuation, invoked within the clause's declared grade.
        _context
            Runtime services, unused by this clause.

        Returns
        -------
        object
            What the resumed computation produced, or a `Forward` when
            the site is not intervened.

        Raises
        ------
        InvalidHandlerError
            If the request does not carry a site and a sampleable.
        RuntimeTypeMismatch
            If the value does not inhabit the site's type.
        """
        site, _ = _site_and_sampleable(request, definition.name)
        if site not in values:
            return Forward()
        value = values[site]
        _require(
            value, result_validator, request.core.result_type, f"intervention {site!r}"
        )
        if on_intervene is not None:
            on_intervene(request, value)
        return TailResume(value)

    return RuntimeHandler(
        definition, {RANDOM_SAMPLE: RuntimeClause(sample, result_validator)}
    )

reweight_handler

reweight_handler(transform: Callable[[object], object], *, score_instance: EffectInstanceId, weight_validator: RuntimeValidator = lambda _value: True, answer_type: TypeExpr = ANSWER, key: str = 'reweight') -> RuntimeHandler

Transform every Score.add contribution before passing it outward.

Scaling and masking are transformers: each contribution arriving at the handler is replaced by its image and sent to the same instance's outer handler, with the provenance of the site it came from kept.

PARAMETER DESCRIPTION
transform

The map applied to each contribution.

TYPE: Callable[[object], object]

score_instance

The lexical Score instance handled, which the transformed contribution is sent on to.

TYPE: EffectInstanceId

weight_validator

Checks each transformed contribution.

TYPE: RuntimeValidator DEFAULT: lambda _value: True

answer_type

What the handler answers with.

TYPE: TypeExpr DEFAULT: ANSWER

key

Distinguishes this handler from others of the same name, entering its derived identity.

TYPE: str DEFAULT: 'reweight'

RETURNS DESCRIPTION
RuntimeHandler

The attachment, ready to bind into a runtime environment.

Source code in src/quivers/qiec/builtins.py
def reweight_handler(
    transform: Callable[[object], object],
    *,
    score_instance: EffectInstanceId,
    weight_validator: RuntimeValidator = lambda _value: True,
    answer_type: TypeExpr = ANSWER,
    key: str = "reweight",
) -> RuntimeHandler:
    """Transform every ``Score.add`` contribution before passing it outward.

    Scaling and masking are transformers: each contribution arriving at
    the handler is replaced by its image and sent to the same instance's
    outer handler, with the provenance of the site it came from kept.

    Parameters
    ----------
    transform
        The map applied to each contribution.
    score_instance
        The lexical `Score` instance handled, which the transformed
        contribution is sent on to.
    weight_validator
        Checks each transformed contribution.
    answer_type
        What the handler answers with.
    key
        Distinguishes this handler from others of the same name,
        entering its derived identity.

    Returns
    -------
    RuntimeHandler
        The attachment, ready to bind into a runtime environment.
    """
    definition = _handler_def(
        "Score.reweight",
        SCORE,
        ((SCORE_ADD, ResumptionGrade.LINEAR),),
        key=key,
        input_type=answer_type,
        output_type=answer_type,
        introduced=EffectRow((RowEntry(score_instance, SCORE),)),
        telescope=_generic_binders(answer_type=answer_type),
    )

    def add(
        request: RuntimeRequest,
        resume: Resumption,
        context: ClauseContext,
    ) -> object:
        """Answer a `Score.add` request by re-emitting the transformed weight.

        Parameters
        ----------
        request
            The request being answered and its arguments.
        resume
            The continuation, invoked within the clause's declared grade.
        context
            Runtime services available to the clause.

        Returns
        -------
        object
            What the resumed computation produced.

        Raises
        ------
        InvalidHandlerError
            If the request does not carry exactly one argument.
        RuntimeTypeMismatch
            If the transformed contribution does not inhabit the weight
            type.
        """
        (weight,) = _expect_arguments(request, 1, definition.name)
        # The transformed contribution keeps the role the original was
        # emitted under, so a reader of the accumulator still knows
        # whether the site was drawn, conditioned, or replayed.
        _emit_score(
            context,
            request,
            score_instance,
            transform(weight),
            weight_validator,
            role=request.core.origin.origin.role,
        )
        return TailResume(None)

    return RuntimeHandler(definition, {SCORE_ADD: RuntimeClause(add, _unit)})

block_handler

block_handler(hidden: Callable[[object], bool], *, score_instance: EffectInstanceId, result_validator: RuntimeValidator, weight_validator: RuntimeValidator = lambda _value: True, draw: Callable[[object, object, RuntimeRequest], object] | None = None, answer_type: TypeExpr = ANSWER, key: str = 'block') -> RuntimeHandler

Answer hidden sites locally so no outer handler sees them.

A hidden site is drawn and scored here, exactly as the default scoring draw would; every other site forwards.

PARAMETER DESCRIPTION
hidden

Whether a site is hidden from the handlers outside this one.

TYPE: Callable[[object], bool]

score_instance

The lexical Score instance a hidden draw's log density is sent to.

TYPE: EffectInstanceId

result_validator

Checks the value a resumption carries inhabits the operation's result type.

TYPE: RuntimeValidator

weight_validator

Checks each log-density contribution.

TYPE: RuntimeValidator DEFAULT: lambda _value: True

draw

Supplies the drawn value for a hidden site, given the site, the sampleable, and the request. None uses the sampleable's own sampling interface.

TYPE: Callable[[object, object, RuntimeRequest], object] | None DEFAULT: None

answer_type

What the handler answers with.

TYPE: TypeExpr DEFAULT: ANSWER

key

Distinguishes this handler from others of the same name, entering its derived identity.

TYPE: str DEFAULT: 'block'

RETURNS DESCRIPTION
RuntimeHandler

The attachment, ready to bind into a runtime environment.

Source code in src/quivers/qiec/builtins.py
def block_handler(
    hidden: Callable[[object], bool],
    *,
    score_instance: EffectInstanceId,
    result_validator: RuntimeValidator,
    weight_validator: RuntimeValidator = lambda _value: True,
    draw: Callable[[object, object, RuntimeRequest], object] | None = None,
    answer_type: TypeExpr = ANSWER,
    key: str = "block",
) -> RuntimeHandler:
    """Answer hidden sites locally so no outer handler sees them.

    A hidden site is drawn and scored here, exactly as the default
    scoring draw would; every other site forwards.

    Parameters
    ----------
    hidden
        Whether a site is hidden from the handlers outside this one.
    score_instance
        The lexical `Score` instance a hidden draw's log density is sent
        to.
    result_validator
        Checks the value a resumption carries inhabits the operation's
        result type.
    weight_validator
        Checks each log-density contribution.
    draw
        Supplies the drawn value for a hidden site, given the site, the
        sampleable, and the request. None uses the sampleable's own
        sampling interface.
    answer_type
        What the handler answers with.
    key
        Distinguishes this handler from others of the same name,
        entering its derived identity.

    Returns
    -------
    RuntimeHandler
        The attachment, ready to bind into a runtime environment.
    """
    definition = _handler_def(
        "Random.block",
        RANDOM,
        ((RANDOM_SAMPLE, ResumptionGrade.LINEAR),),
        key=key,
        input_type=answer_type,
        output_type=answer_type,
        introduced=EffectRow((RowEntry(score_instance, SCORE),)),
        total=False,
        telescope=_generic_binders(answer_type=answer_type),
    )

    def sample(
        request: RuntimeRequest,
        resume: Resumption,
        context: ClauseContext,
    ) -> object:
        """Answer a hidden site's `Random.sample` request locally.

        Parameters
        ----------
        request
            The request being answered and its arguments.
        resume
            The continuation, invoked within the clause's declared grade.
        context
            Runtime services available to the clause.

        Returns
        -------
        object
            What the resumed computation produced, or a `Forward` for a
            site that is not hidden.

        Raises
        ------
        InvalidHandlerError
            If the request does not carry a site and a sampleable, or the
            sampleable offers no sampling or scoring interface.
        """
        site, sampleable = _site_and_sampleable(request, definition.name)
        if not hidden(site):
            return Forward()
        value = (
            draw(site, sampleable, request)
            if draw is not None
            else _default_draw(sampleable)
        )
        _emit_score(
            context,
            request,
            score_instance,
            _log_density(sampleable, value),
            weight_validator,
            role="block-score",
        )
        return TailResume(value)

    return RuntimeHandler(
        definition, {RANDOM_SAMPLE: RuntimeClause(sample, result_validator)}
    )

compute_handler

compute_handler(function: Callable[[object, ClauseContext], object], *, effect: EffectRef, result_validator: RuntimeValidator, introduced: EffectRow = EffectRow(), answer_type: TypeExpr = ANSWER, key: str = 'compute') -> RuntimeHandler

Serve a Compute instance with a host function.

PARAMETER DESCRIPTION
function

The host function, called with the request's argument and the clause context, through which it may perform effects the introduced row names.

TYPE: Callable[[object, ClauseContext], object]

effect

The applied Compute[X, A] interface the instance carries.

TYPE: EffectRef

result_validator

Checks the function's result inhabits the operation's result type.

TYPE: RuntimeValidator

introduced

Effects the host function performs.

TYPE: EffectRow DEFAULT: EffectRow()

answer_type

What the handler answers with.

TYPE: TypeExpr DEFAULT: ANSWER

key

Distinguishes this handler from others of the same name, entering its derived identity.

TYPE: str DEFAULT: 'compute'

RETURNS DESCRIPTION
RuntimeHandler

The attachment, ready to bind into a runtime environment.

Source code in src/quivers/qiec/builtins.py
def compute_handler(
    function: Callable[[object, ClauseContext], object],
    *,
    effect: EffectRef,
    result_validator: RuntimeValidator,
    introduced: EffectRow = EffectRow(),
    answer_type: TypeExpr = ANSWER,
    key: str = "compute",
) -> RuntimeHandler:
    """Serve a ``Compute`` instance with a host function.

    Parameters
    ----------
    function
        The host function, called with the request's argument and the
        clause context, through which it may perform effects the
        ``introduced`` row names.
    effect
        The applied ``Compute[X, A]`` interface the instance carries.
    result_validator
        Checks the function's result inhabits the operation's result
        type.
    introduced
        Effects the host function performs.
    answer_type
        What the handler answers with.
    key
        Distinguishes this handler from others of the same name,
        entering its derived identity.

    Returns
    -------
    RuntimeHandler
        The attachment, ready to bind into a runtime environment.
    """
    definition = _handler_def(
        "Compute.host",
        effect,
        ((COMPUTE_APPLY, ResumptionGrade.LINEAR),),
        key=key,
        input_type=answer_type,
        output_type=answer_type,
        introduced=introduced,
        telescope=_generic_binders(answer_type=answer_type),
    )

    def apply(
        request: RuntimeRequest,
        resume: Resumption,
        context: ClauseContext,
    ) -> object:
        """Answer a `Compute.apply` request with the host function's result.

        Parameters
        ----------
        request
            The request being answered and its arguments.
        resume
            The continuation, invoked within the clause's declared grade.
        context
            Runtime services available to the clause.

        Returns
        -------
        object
            What the resumed computation produced.

        Raises
        ------
        InvalidHandlerError
            If the request does not carry exactly one argument.
        """
        (argument,) = _expect_arguments(request, 1, definition.name)
        return TailResume(function(argument, context))

    return RuntimeHandler(
        definition, {COMPUTE_APPLY: RuntimeClause(apply, result_validator)}
    )

param_handler

param_handler(lookup: Callable[[str, RuntimeRequest], object], *, result_validator: RuntimeValidator, total: bool = True, answer_type: TypeExpr = ANSWER, key: str = 'param') -> RuntimeHandler

Serve Param.get from a host parameter store.

PARAMETER DESCRIPTION
lookup

Returns the value of the named parameter, given the name and the request.

TYPE: Callable[[str, RuntimeRequest], object]

result_validator

Checks a value inhabits the request's result type.

TYPE: RuntimeValidator

total

Whether the handler discharges the instance; a handler layered over a store leaves the instance in the row so the store stays required outside it.

TYPE: bool DEFAULT: True

answer_type

What the handler answers with.

TYPE: TypeExpr DEFAULT: ANSWER

key

Distinguishes this handler from others of the same name, entering its derived identity.

TYPE: str DEFAULT: 'param'

RETURNS DESCRIPTION
RuntimeHandler

The attachment, ready to bind into a runtime environment.

Source code in src/quivers/qiec/builtins.py
def param_handler(
    lookup: Callable[[str, RuntimeRequest], object],
    *,
    result_validator: RuntimeValidator,
    total: bool = True,
    answer_type: TypeExpr = ANSWER,
    key: str = "param",
) -> RuntimeHandler:
    """Serve ``Param.get`` from a host parameter store.

    Parameters
    ----------
    lookup
        Returns the value of the named parameter, given the name and the
        request.
    result_validator
        Checks a value inhabits the request's result type.
    total
        Whether the handler discharges the instance; a handler layered
        over a store leaves the instance in the row so the store stays
        required outside it.
    answer_type
        What the handler answers with.
    key
        Distinguishes this handler from others of the same name,
        entering its derived identity.

    Returns
    -------
    RuntimeHandler
        The attachment, ready to bind into a runtime environment.
    """
    definition = _handler_def(
        "Param.store",
        PARAM,
        ((PARAM_GET, ResumptionGrade.LINEAR),),
        key=key,
        input_type=answer_type,
        output_type=answer_type,
        total=total,
        telescope=_generic_binders(answer_type=answer_type),
    )

    def get(
        request: RuntimeRequest,
        resume: Resumption,
        _context: ClauseContext,
    ) -> object:
        """Answer a `Param.get` request with the stored value.

        Parameters
        ----------
        request
            The request being answered and its arguments.
        resume
            The continuation, invoked within the clause's declared grade.
        _context
            Runtime services, unused by this clause.

        Returns
        -------
        object
            What the resumed computation produced.

        Raises
        ------
        InvalidHandlerError
            If the request does not carry exactly one string argument.
        RuntimeTypeMismatch
            If the value does not inhabit the request's result type.
        """
        (name,) = _expect_arguments(request, 1, definition.name)
        if not isinstance(name, str):
            raise InvalidHandlerError("Param.get takes a parameter name")
        value = lookup(name, request)
        _require(
            value, result_validator, request.core.result_type, f"parameter {name!r}"
        )
        return TailResume(value)

    return RuntimeHandler(definition, {PARAM_GET: RuntimeClause(get, result_validator)})