You're viewing the readable version of this site. The interactive extras (search, diagrams, read-aloud) need JavaScript and a current browser. Enable JavaScript; if it is already enabled, update your browser.

Learn · The Concrete Discrete Math of Real Systems · Companion lesson

seedling

An Effect Is a Request

Keep decisions pure, describe work as data, and give the outside world only the capabilities a component is allowed to use.

discrete-math, effects, capabilities, cancellation, deterministic-testing, learn

We therefore obtain a new concept of computation that includes operations with a computational effect.

Gordon Plotkin and Matija Pretnar, “Handlers of Algebraic Effects,” 2009

The main route kept its evaluators pure, so it did not need a chapter about clocks, network requests, timers, cancellation, or browser APIs. Real components do. This companion fills that gap. You will separate a decision from its performance, model effects as a finite data type, interpret them through explicit capabilities, and test cancellation and resource ownership without waiting for wall-clock accidents.

The callback did too much

A search update reads the query, starts a timer, aborts an old request, fetches new results, changes a loading flag, and eventually moves focus. When all of that happens inside callbacks, the program has mixed two questions:

  1. what should happen next?
  2. how does this platform make it happen?

Make the first answer data:

start-timer(id, delay)
cancel-timer(id)
request-results(requestId, query)
cancel-request(requestId)
announce(message)
focus(target)

Now the update function returns a new state and a finite sequence of requests. A browser interpreter performs them. A simulator records them and delivers completions in any admitted order.

An effect value is a request for the world to act, not evidence that the action already happened.

Effects are another algebraic data type

The effect language is a sum: an effect is a timer or request or announcement or focus command. Each alternative carries exactly the data its interpreter needs. Structural induction from Chapter 4 now supplies the interpreter's proof checklist: handle every constructor.

A finite sequence of effects is also a monoid. The empty sequence does nothing; concatenation combines independent requests; reassociation does not change their order. That does not make arbitrary effects commutative. focus(input) followed by focus(option) differs from the reverse. The algebra tells us exactly which freedom we purchased and which we did not.

A capability is authority, not convenience

An interpreter should receive a small explicit world: perhaps now, setTimer, request, and announce. The set of available operations is the component's authority. If no storage or network capability crosses the boundary, the component cannot silently use storage or the network.

Capabilities also make tests honest. A simulated clock advances only when the test says so. A scripted request performer can return the second query before the first. The same seed and event log reproduce the same run because ambient time and entropy never leak into the decision function.

Cancellation is an ownership transition

The DOM Standard's abort model represents cancellation with a signal. The mathematical issue arrives before the API call: which state owns the right to publish a completion?

Let each request have an identity. Starting a newer request transfers publication ownership. A completion may update visible results only when its identity equals the currently owned identity. Aborting old work saves resources, but the identity check preserves correctness even if the old completion was already queued.

Prediction — identify the correctness boundary.

Budgets form an ordered resource contract

Effects consume finite resources: requests, bytes, timers, descendants, and time. Represent a budget as a vector of nonnegative bounds. One budget is no more permissive than another when every coordinate is less than or equal to its counterpart. That is a partial order from Chapter 5, now acting as an admission rule.

A component may request an effect only if the remaining budget admits it. Exhaustion is a typed outcome, not an exception or a silently dropped action. Tests generate plans near zero, one, and maximum capacity because those boundaries change the transition graph.

What the harness can establish

  • Purity by replay: the same initial state and event trace produce the same next states and effect values.
  • Total handling: every effect constructor has an interpreter case.
  • Authority: interpreters expose only declared capabilities.
  • Ownership: only the current request, timer, or focus scope may publish.
  • Cleanup: destroy reaches a state with no owned resources.
  • Bounds: admitted traces never spend more than their resource vector.

Platform conformance remains a second layer. A simulated timer proves the component's scheduling decisions; it does not prove a browser paints the result without layout shift. That is where the component journey and its geometry, accessibility, motion, and performance witnesses return.

Lessons

  • Describe effects as data and keep transition decisions pure.
  • An interpreter turns the effect language into platform actions; a simulator turns the same language into deterministic evidence.
  • Cancellation saves work, while identity-based ownership preserves correctness.
  • Capability sets and resource budgets make authority and limits visible.

Practice

  1. List every effect a delayed tooltip may request. Which commute, and which must retain order?
  2. Write the stale-completion transition for an autocomplete. Make ignoring the obsolete result an explicit case.
  3. Give a component a timer budget of zero. Should the event be rejected, degraded to immediate work, or represented as exhaustion? State the contract rather than choosing silently.
  4. One week later, explain why aborting a request and owning its result are related but different guarantees.

References

  1. Plotkin and Pretnar. “Handlers of Algebraic Effects.” ESOP, 2009. — primary account of operations and handlers
  2. WHATWG. “Aborting ongoing activities.” DOM Standard, current. — platform cancellation model
  3. Elm. “The Elm Architecture.” Official Guide, current. — model, update, view, and command separation in user interfaces