Playground
Everything on this page runs the real fugue crate, compiled to
WebAssembly. The editor below speaks a subset of the prob! macro language;
when you press Run, your model text is parsed in Rust, folded into
actual Model combinators, and handed to the same inference kernels this
book documents — adaptive Metropolis–Hastings one transition at a time,
Hamiltonian Monte Carlo with dual-averaging warmup, adaptive tempered SMC
with a log-evidence estimate. The draws you watch stream in are fugue's
draws, not a JavaScript imitation of them.
What the editor understands
The playground accepts the statement forms of prob!, with data arrays
provided as JSON (an object of named arrays, or a bare array bound to
data):
let p <- sample(addr!("p"), Beta(2.0, 2.0)); // sample a latent
let m = 2.0 * p - 1.0; // deterministic let
observe(addr!("y"), Normal(m, 0.8), 1.4); // condition on data
factor(-0.5 * m * m); // add a log-weight
for i in 0..data.len() { ... } // plates
pure(p) // the model's return value
Rust spellings from the docs paste in unchanged — Normal::new(0.0, 1.0).unwrap()
parses the same as Normal(0.0, 1.0). Available distributions: Normal,
Uniform, LogNormal, Exponential, Beta, Gamma, InverseGamma,
StudentT, Cauchy, Laplace, Weibull, ChiSquared, Bernoulli,
Binomial, Poisson, Categorical, DiscreteUniform — the same
constructors, parameterizations, and support checks as the crate, because
they are the crate. Expressions know + - * /, exp, ln, sqrt,
abs, pow, min, max, floor, sin, cos, tanh, array indexing
y[i], and .len().
Two honest limitations: parameter regions that would make a distribution
invalid (say, a negative scale reached through your arithmetic) score as
impossible (-inf) rather than erroring, exactly how the samplers treat
leaving a support; and the interpreter covers the statement subset above,
not arbitrary Rust — for that, there is cargo add fugue-ppl.
Things to try
- Watch R̂ earn its keep. Run the coin-flip preset with 3 chains: the
chains start from independent prior draws, disagree, then R̂ falls
toward 1.00 as their histograms merge — the same split-R̂ computation
fugue::inference::diagnosticsruns in production. - Break a model, kindly. Change a flip observation to
2.0(a coin that landed on its edge?).Bernoulliobserves a boolean, so anything nonzero coerces totrue— then make the priorBeta(0.5, 0.5)and watch the posterior bend toward the edges. - Compare kernels on the same posterior. Run the eight-schools preset under MH, then under HMC. Single-site MH updates one coordinate at a time and mixes slowly through the funnel; HMC moves all ten coordinates jointly. The ESS readout is the receipt.
- Ask for evidence. Switch to SMC on any preset: you get weighted
posterior particles and
log Z, the marginal likelihood MH and HMC never give you. - Make it yours. Replace the data JSON with your own numbers. The model recompiles as you type — the ✓/✗ line is fugue's parser talking.
How this works
crates/fugue-wasm (in the fugue repository) exposes wasm-bindgen entry
points over the crate: compile a model source + data payload, then drive
step(n) per animation frame and read draws and diagnostics back as typed
arrays. Sampler state lives in Rust — traces, adaptation state, tuned step
sizes — and every run is seeded, so a seed is a replayable recording here
too. The interactive figures in the explorables chapters use the same
package for their samplers; only their canvas rendering is JavaScript.
Go deeper
- Explorables: Random Walks in Posterior Space, Rolling, Not Guessing: HMC, Particles That Tell Stories — the guided tours of the kernels this playground exposes.
- The real thing: Installation —
cargo add fugue-ppland the fullprob!language, typed traces, custom handlers. - API: docs.rs/fugue-ppl.