lazyppl
Lazy Probabilistic Programming Library
https://lazyppl-team.github.io/
| LTS Haskell 23.28: | 1.0 |
| Stackage Nightly 2026-11-08: | 1.1.0.1 |
| Latest on Hackage: | 1.1.0.1 |
lazyppl-1.1.0.1@sha256:b20987af5b12612e6a6648ca4fa2b40e5cc53e6bde8ad758989adc23969869de,6906Module documentation for 1.1.0.1
LazyPPL
LazyPPL is a Haskell library for Bayesian probabilistic programming, drawing on the fact that lazy data structures are a natural idiom for programming with infinite-dimensional Bayesian methods such as Poisson/Gaussian/Dirichlet processes.
The crucial semantic idea, inspired by developments in synthetic probability theory, is to work with two separate monads: an affine monad of probability, which supports laziness, and a commutative, non-affine monad of measures, which does not. This gives a Metropolis-Hastings implementation that works with lazy programs.
The main LazyPPL modules are on Hackage and Stackage. Various worked examples in literate Haskell are at https://lazyppl-team.github.io.
Laziness lets us specify non-parametric models cleanly: processes or infinite-dimensional functions only have their finite explored portion materialised. We have first-class
- stochastic memoization:
memoize :: (a -> Prob b) -> Prob (a -> b) - Gaussian processes:
wiener :: Prob (Double -> Double) - point processes:
poissonPP :: Double -> Double -> Prob [Double](in the example demos) - Dirichlet processes:
dp :: Double -> Prob a -> Prob (Prob a)
Examples
WienerDemo(lhs) is a simple implementation of regression using a Wiener process. Via maintaining a hidden table of previous calls, it appears to be a bona fide random function $R\to R$ constructed lazily. Some values are sampled during simulation, others during plotting.
RegressionDemo(lhs) demonstrates piecewise linear regression. The change points are drawn from a lazy Poisson process.
Clustering(lhs) contains some simple clustering examples, where the number of clusters is unknown. Stick-breaking is lazy, and we use stochastic memoization.
ProgramInduction(lhs) is a simple example of program induction over an arithmetic language. Random expressions are represented as an infinite forest with a finite path through it.
- Feature extraction via the Indian Buffet Process, and relation inference via the Mondrian Process and a Chinese-Restaurant-Process-based Infinite Relational Model.
Library
LazyPPL.hsprovides the core monads and inference.Probis an affine monad of probability measures.Measis a non-affine monad of unnormalised measures withsampleandscore. The Metropolis-Hastings algorithmmhtakes a probabilitypof changing any given site of the rose tree of random seeds. Settingp=1/num_sitesapproximates single-site MH andp=1recovers multi-site MH. We can’t compute the number of active sites without forcing more of the lazy tree, so we use thisp-parameterised form. A second algorithm,mh1inlazyppl-singlesite, implements a single-site proposal kernel by inspecting the Haskell heap.LazyPPL/Distributions.hsandLazyPPL/Distributions/*provide common distributions and abstract types capturing exchangeability. For example,newCustomer :: Restaurant -> Prob Tablefor the Chinese Restaurant Process (DirichletP.hs) andRestaurant -> Prob [Dish]for the Indian Buffet Process (IBP.hs).
Installation
Build with Cabal: install GHCup for GHC 9.14.1 and Cabal 3.18.2.0, then cabal update and cabal build in the repo root. First build takes a few minutes.
Run a demo: cabal run -fdemos wiener-exe (or regression-exe, clustering-exe, etc.), or explore in the REPL with cabal repl lib:lazyppl.
The library is pure Haskell and needs no LAPACK or BLAS installation. The plotting demos use the matplotlib Haskell wrapper, which calls into Python: sudo apt-get install -y --no-install-recommends python3-matplotlib python3-numpy python3-scipy python-is-python3.
To try lazyppl in your browser without installing anything, click . This opens a ready-to-use VS Code environment with GHC and Cabal already in place.
Writing your own probabilistic models
Under executables: in examples/package.yaml, add a stanza and run hpack examples (0.39.6) to regenerate examples/lazyppl-examples.cabal:
executables:
# ...
mymodel-exe:
main: MyModel.hs
source-dirs: models
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
- -main-is MyModel
dependencies:
- lazyppl
Run with cabal run mymodel-exe, or open in the REPL: cabal repl exe:mymodel-exe.
Changes
Changelog for lazyppl
1.1.0.1
Fixed
wis: when the log weights were large and equal, adding them rounded, so the cumulative weights all equalled the maximum and the first particle always won.wisnow resamples in log space through the bounded categorical sampler ofmwc-random, so equal large weights share the resamples; fixed-seed results change.
1.1.0
Added
lazyppl-examples: separate examples and plotting package- Playground: interactive browser models
- Example pages: locally served fonts and icons
Changed
- Build: Cabal and GHC 9.6.7, 9.12.4, 9.14.1
gp,wiener: pure Haskell without LAPACKmh,mhirreducible: lower stream memory retentionmemrec:Ordkeys withoutShow- Integer
memoize: restricted toProb - Distributions: validate inputs and parameter domains
beta,dirichlet: reject unsupported shape parameters- Random labels and acceptance draws: open interval (0,1)
mh,mhirreducible,weightedsamples,wis: separate generator per runsuperuniformbounded: bounded graph angle sampling
Fixed
wis: resample from all weighted samples- Integer
memoize: return values at their own indices mh,mhirreducible,wis: zero and invalid weightsmh1: reject proposals without reverse sitesbeta,dirichlet: sampling at numerical boundariesbeta,dirichlet: reject unsupported custom tree labelscategorical: rounding with finite and infinite streamscategorical: accept finite probabilities with a rounding-sized shortfall- Dirichlet processes: small-stick accumulation
poisson: sampling at extreme labelsibp: first customer’s dish countgp: initial and conditional distributionswiener: variance at extreme timesnormalLogPdf,betaLogPdf,dirichletLogPdf: extreme-input accuracybinomialLogPmf: large-count accuracygammaLogPdf,poissonLogPmf: extreme-input accuracy- Memoization, Gaussian processes and counters: concurrent state
uniformbounded,uniformBoundedLogPdf: overflowing bound differences- Playground: retry failed WebAssembly downloads
- Playground: validate results before plotting
- Mondrian playground: reject overlaps and duplicate identifiers
- GraphDemo: graph probabilities and figure edges
- Example pages: correct maximum-likelihood sample labels
- Example pages: syntax colours in dark mode
- Website generation: preserve prior site on build failure
Removed
LazyPPL.SingleSite: moved tolazyppl-singlesitelazyppl:hmatrix, LAPACK and plotting dependencies
1.0.1
- Add support for GHC 9.8 and 9.10
- Drop upper bounds on dependencies (except
base) - Add log-density / log-PMF functions:
normalLogPdf,gammaLogPdf, etc. - Export
scoreLogandscoreProductLog(already defined in 1.0, now visible) - Remove
monad-extrasdependency
1.0
- Initial Hackage release