During my telecommunications degree I took a course on signals and noise, I spent a lot of evenings writing probability by hand: expectations, variances, the odds of two random variables landing in some region. It always sucked, when I tried to run it on a computer, so much boilerplate.
That wish became NoiseLang. I started it about nine years ago, however, I never finished it. Only recently, I brought it back thanks to AI tools and something far more ambitious than what I could have built alone the first time.
Everything is a distribution
The whole language hangs on one idea, that every value is a probability distribution. A plain number is a Dirac spike, a distribution with all its weight on a single value. Since constants and random variables are the same kind of object, every operator in the language maps distributions to distributions.
A name always refers to one fixed node, the same way X is the same X across a whole page of math. So X + X is 2X and X - X is exactly 0 ,. If you want variable independence you write separate draws, ie, using ~ multiple times, or ~[N] to draw N independent variables into a vector.
X ~ unif_int(1, 6) Y ~ unif_int(1, 6) X + Y # two independent dice, a real 2d6 distribution
Nothing runs until you ask for some results, for example, P(X + Y < 10) , at that moment it forces the runtime to run millions of simulations (across all cores, if available) and return an estimate with a standard error attached.
Bday = unif_int(1, 365) days ~[23] Bday # 23 people in a room P(has_duplicates(days)) # the birthday paradox, about 0.507
This is much easier to watch than to describe, so I built some cool demos!
Every value is a distribution A = 5 D1 ~ unif_int(1, 6) D2 ~ unif_int(1, 6) S = A + D1 + D2 E(S) Figure 1. The same histogram through four steps: a constant is a single spike, the tilde spreads it into a die, adding two dice curves it toward a bell, and a query reads the mean back. A number is a distribution A = 5 looks like a plain constant, and it is, but Noise sees it as a probability distribution where every draw lands on 5. Statisticians call this a Dirac delta, a single infinitely-thin spike. The tilde spreads it out D1 ~ unif_int(1, 6) binds a fair die, a discrete uniform where all six faces are equally likely. The spike fans out into six flat bars, so D1 is now uncertain, but you still write it like any other variable. Join them and a bell appears Add the constant and two independent dice with S = A + D1 + D2 . The flat shapes convolve into a triangle peaked at 12, already curving toward a bell, and if you join a few more they sharpen into a true Gaussian. That's the central limit theorem showing up for free! A query collapses millions of draws Nothing runs until you ask. E(S) , the expected value, fires a Monte Carlo pass that averages millions of rolls into one number, and by the law of large numbers the running mean settles on 12 . You wrote a few lines of math, and an expert-level kernel ran underneath.
... continue reading