Fugue is a production-ready, monadic probabilistic programming library for Rust. It enables elegant probabilistic program composition through Model values executed with pluggable interpreters and state-of-the-art inference algorithms.
- Monadic Design: Compose probabilistic programs using pure functional abstractions
- Type Safety: Natural return types for distributions (Bernoulli →
bool, Poisson →u64) - Production Ready: Numerically stable algorithms with comprehensive error handling
- Performance Focused: Memory optimization, copy-on-write traces, efficient algorithms
fugue/
├── src/ # Core library implementation
│ ├── core/ # Fundamental PPL primitives (Model, Distribution, Address)
│ ├── runtime/ # Execution engine (Handlers, Interpreters, Traces)
│ ├── inference/ # Algorithms (MCMC, SMC, VI, ABC)
│ └── error.rs # Comprehensive error handling
├── docs/ # User documentation (mdbook)
├── examples/ # Practical usage examples
├── tests/ # Integration and API tests
└── benches/ # Performance benchmarks
Model<T>: Core probabilistic program typesample(): Draw from distributionsobserve(): Condition on dataprob!macro: Do-notation for monadic composition
- Every random choice has a unique, stable address
- Format:
"name","name#index","scope::name","scope::name#index" - Critical for reproducibility and inference targeting
PriorHandler: Forward sampling from priorsReplayHandler: Replay with specific trace valuesScoreGivenTrace: Score traces for importance sampling- Safe variants available for production use
Always run tests after making changes. This is critical for a probabilistic programming library where subtle changes can have significant statistical implications.
# Always run before committing changes
make all
# For quick feedback during development
make test
# Check test coverage
make coverage- Follow standard Rust conventions (rustfmt, clippy)
- Prefer explicit error handling over panics
- Use type-safe abstractions over raw implementations
- Document public APIs with examples
- Unit tests for individual components
- Integration tests for end-to-end workflows
- Property-based testing for numerical stability
- Benchmark critical performance paths
- Numerical Stability: Use log-space computations, guard against overflow/underflow
- Reproducibility: Ensure deterministic execution given same random seed
- Memory Management: Consider trace pooling for high-throughput applications
- Error Propagation: Preserve error context through the computation stack
- Implement
Distribution<T>trait insrc/core/distribution.rs - Add validation logic and error handling
- Include comprehensive tests with edge cases
- Document mathematical properties and use cases
- Design around existing
Handlerinfrastructure - Consider trace manipulation patterns
- Implement convergence diagnostics
- Provide both basic and production-ready variants
- Profile with realistic workloads first
- Consider memory pooling for frequent allocations
- Use copy-on-write semantics where appropriate
- Benchmark against baseline implementations
make test: Run test suitemake lint: Run clippy lintermake fmt: Format codemake doc: Generate and open documentationmake mdbook: Build mdbook documentationmake coverage: Generate coverage reportmake bench: Run benchmarksmake all: Run all checks (format, lint, test, coverage)
# Build and test
make test
# Run examples
cargo run --example basic_modeling
# Generate documentation
make docs-all
# Format and lint
make fmt
make lint
# Run all checks
make all- Probabilistic Programming Theory: Understanding of measure theory, inference algorithms
- Numerical Analysis: Floating-point precision, log-space computations
- Rust Systems Programming: Memory management, zero-cost abstractions
- Statistical Computing: Convergence diagnostics, sampling strategies
- Changes should preserve API compatibility where possible
- New features require comprehensive tests and documentation
- Performance-critical changes need benchmark validation
- All public APIs must include usage examples
For detailed contribution guidelines, see .github/CONTRIBUTING.md.