Design + ops scaffolding for the next phase of work, none of it touching
substrate or guest code.
lib-guest.md: rewrites Architectural framing as a 5-layer stack
(substrate → lib/guest → languages → shared/ → applications),
recursive dependency-direction rule, scaled two-consumer rule. Adds
Phase B (long-running stratification) with sub-layer matrix
(core/typed/relational/effects/layout/lazy/oo), language profiles, and
the long-running-discipline section. Preserves existing Phase A
progress log and rules.
ocaml-on-sx.md: scope reduced to substrate validation + HM + reference
oracle. Phases 1-5 + minimal stdlib slice + vendored testsuite slice.
Dream carved out into dream-on-sx.md; Phase 8 (ReasonML) deferred.
Records lib-guest sequencing dependency.
datalog-on-sx.md: adds Phase 4 built-in predicates + body arithmetic,
Phase 6 magic sets, safety analysis in Phase 3, Non-goals section.
New chisel plans (forward-looking, not yet launchable):
kernel-on-sx.md — first-class everything, env-as-value endgame
idris-on-sx.md — dependent types, evidence chisel
probabilistic-on-sx.md — weighted nondeterminism + traces
maude-on-sx.md — rewriting as primitive
linear-on-sx.md — resource model, artdag-relevant
Loop briefings (4 active, 1 cold):
minikanren-loop.md, ocaml-loop.md, datalog-loop.md, elm-loop.md, koka-loop.md
Restore scripts mirror the loop pattern:
restore-{minikanren,ocaml,datalog,jit-perf,lib-guest}.sh
Each captures worktree state, plan progress, MCP health, tmux status.
Includes the .mcp.json absolute-path patch instruction (fresh worktrees
have no _build/, so the relative mcp_tree path fails on first launch).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7.9 KiB
Probabilistic-on-SX: weighted nondeterminism + traces + inference
Programs declare distributions; the runtime infers. The most orthogonal addition to the set — every existing guest treats execution as deterministic-or-resumable. Probabilistic programming requires weighted, traceable executions with explicit posterior-inference machinery on top. Anglican (Wood et al.) or Church (Goodman et al.) is the closest reference; we'll target a Church-flavoured core.
The chisel: trace. What does it mean to record an execution? What's a probability weight? How do branches in conde-like nondeterminism differ from sample/observe choices? The substrate has multi-shot continuations (a prerequisite for any decent inference algorithm) but doesn't articulate weights or traces — implementing a probabilistic language forces it to.
What this exposes about the substrate:
- Whether
cek-resumecan be invoked many times perperformwith different values (multi-shot we know works; parameterised multi-shot is the question). - Whether traces — sequences of (random-variable-id, sampled-value, log-weight) — fit naturally in the value space.
- Whether the substrate can support efficient trace replay (start a fresh execution but force certain random choices to specific values).
- Whether handler/effect machinery (lib/guest/effects/ when it exists) can host inference-as-handler.
End-state goal: Anglican-style probabilistic Scheme — sample, observe, basic distribution library, importance sampling, MCMC (Metropolis-Hastings), and a path to variational inference. Programs are distributions; query expr returns a distribution over outcomes.
Ground rules
- Scope:
lib/probabilistic/**andplans/probabilistic-on-sx.mdonly. Substrate gaps →sx-improvements.md. - Consumes from
lib/guest/:core/lex,core/pratt,core/ast,core/match. Possiblyeffects/once that sub-layer exists (inference algorithms are naturally handlers oversample/observe). - May propose
lib/guest/probabilistic/sub-layer — trace-recording infrastructure, weight-algebra primitives (log-domain arithmetic), inference combinators, distribution constructors. Second consumer would be a future Pyro-style language or a Bayesian DSL. - Branch:
loops/probabilistic. Standard worktree pattern.
Architecture sketch
Probabilistic source text (Church-flavoured: scheme + sample/observe)
│
▼
lib/probabilistic/parser.sx — s-expression reader
│
▼
lib/probabilistic/eval.sx — pure evaluator (deterministic except at sample/observe)
│ sample/observe are perform-shaped: suspend execution,
│ let inference algorithm decide what to do
▼
lib/probabilistic/inference/ — handlers that interpret sample/observe:
│ importance.sx importance sampling, likelihood-weighting
│ mh.sx Metropolis-Hastings (proposal kernels)
│ variational.sx mean-field VI
│
▼
lib/probabilistic/distributions.sx — uniform, normal, gamma, beta, dirichlet,
mixture, conditional, etc.
Semantic mappings
| Probabilistic construct | SX mapping |
|---|---|
(sample (uniform 0 1)) |
(perform (:sample (uniform 0 1))) — inference handler decides actual value |
(observe (normal 0 1) 0.5) |
(perform (:observe (normal 0 1) 0.5)) — adds log-prob to weight |
(query body) |
run body under inference handler; return weighted samples |
(uniform a b) |
distribution value: {:type :dist :family :uniform :params (a b)} |
(score lpdf x) |
accumulate log-prob; equivalent to observe |
| Trace | (list (:choice id sampled-value log-weight) ...) — first-class value |
The key trick: sample and observe aren't primitives — they're effect requests. The inference algorithm is a handler that interprets them. Importance sampling samples each sample from the prior and accumulates weights from each observe. MH proposes changes to the trace and accepts/rejects.
Roadmap
Phase 1 — Parser + deterministic core
- Scheme-flavoured parser (s-expressions,
let,lambda,if, arithmetic, lists). - Deterministic evaluator running on SX CEK.
- Tests: standard Scheme programs run.
Phase 2 — sample / observe as effects
sample dist→perform :sample.observe dist value→perform :observe.- Default handler: forward sampling, no inference (just produce a draw).
- Tests: simple stochastic programs (coin flip, sum-of-dice) produce different results across runs.
Phase 3 — Distribution library
uniform,normal,gamma,beta,bernoulli,categorical,dirichlet,poisson.- Each carries
(sample-fn, log-prob-fn). - Tests: log-prob of known density values matches reference.
Phase 4 — Trace recording + replay
- Tracing handler: every
samplerecords{:id :value :log-weight}in a trace value. - Replay handler: given a trace, force
sampleto return the recorded value when called with the sameid. - Tests: record a trace, replay it, get identical outputs.
Phase 5 — Importance sampling
importance-sample n queryrunsqueryntimes under sampling handler.- Each run accumulates log-weights from
observecalls. - Returns weighted samples.
- Tests: posterior over a coin's bias given Bernoulli observations.
Phase 6 — Metropolis-Hastings
mh n queryruns MH fornsteps.- Each step: pick a random choice in the current trace, propose a new value, accept/reject by Hastings ratio.
- Multi-shot continuation usage: re-execute from the proposed-changed point onward.
- Tests: gaussian regression, change-point detection, mixture clustering.
Phase 7 — Mean-field variational inference
- Approximate posterior as product of independent simple distributions.
- Optimise ELBO via gradient ascent.
- Requires automatic differentiation —
lib/probabilistic/autodiff.sx(forward-mode minimum). - Tests: normal-normal model, ELBO converges to known truth.
Phase 8 — Standard library + idioms
- Mixture models, Gaussian processes, hidden Markov models, change-point models.
- Tests: each as an end-to-end test that should give roughly known posteriors.
Phase 9 — Propose lib/guest/probabilistic/
- Identify reusable trace + weight infrastructure (log-domain arithmetic, ESS, sample weighting).
- Wait for a second consumer before extracting.
lib/guest feedback loop
Consumes: core/lex, core/pratt, core/ast, core/match. Future: effects/ for handler-based inference.
Stresses substrate: parameterised multi-shot continuations (each MH step replays from a chosen point with a new value); efficient trace storage; whether perform/cek-resume survives nesting (handler within handler — inference inside another inference).
May propose: lib/guest/probabilistic/ — trace primitives, weight algebra (log-sum-exp etc.), distribution interfaces.
What it teaches: whether SX's effect/continuation machinery is up to real multi-shot work, not just textbook examples. Inference algorithms call cek-resume thousands of times per query; if the substrate has hidden quadratic costs in continuation manipulation, this surfaces them.
References
- Goodman, Mansinghka, Roy, Bonawitz, Tenenbaum, "Church: a language for generative models" (UAI 2008).
- Wood, van de Meent, Mansinghka, "A new approach to probabilistic programming inference" (AISTATS 2014) — Anglican.
- van de Meent, Paige, Yang, Wood, "An Introduction to Probabilistic Programming" (arXiv 2018).
- Bingham et al., "Pyro: Deep Universal Probabilistic Programming" (JMLR 2019).
Progress log
(awaiting Phase 1 — depends on multi-shot continuation stability)
Blockers
(none yet — main concern is hidden substrate costs in continuation manipulation)