Since we're working with superposed values already, a natural expansion of the concept is to that of probabilities. Where by default, if we'd have some superposed values OR'ed, there's a uniform probability distribution. Or in other words.
Evaluated to a single value,
would be 50% each. We can assign probabilities in two ways;
x: String? = 0.2("A") | 0.5("B")
x: String? =
0.2 => "A"
0.5 => "B"
Where any non-covered probabilities, default to None, if the variable is optional. (If the value is non-optional, all cases need to be covered)
Nested probabilities, will of course be supported.
0.5(0.5("A") | 0.5("B")) | "C"
Note that only OR's are evaluated this way, an AND, would not be effected, we can then of course, combine the two. The following for instance:
0.5("A") & 0.5(0.3("B") | 0.7("C"))
Would be two separate probabilities, both evaluated. One for A, and one for B or C.
Note that unless the probabilities are explicitly evaluated to a value, they stay around like any superposed variable.
n (== "A") => 1
n (== "B") => 2
n 0.3("A") | 0.7("B")
We unlock some powerful capabilities like this, I could for instance create the following type:
Binary{-> .next == 0.5(?.random)}
Which is like saying: A randomly generated string of boolean values (possibly infinite) whose length is determined by randomly flipping a coin whether there's a next value.
This syntax requires some unpacking, first consider this:
This is a constructor for a ray which recursively calls the method on an object until none is found. Typically, you'd be able to say things like
And then say things like
(variable -> .parent).last
to get the first parent in some tree.
Then there's
which takes the current type and generates a random instance of it.
To illustrate the power of this new abstraction, you'd then also be able to say something like:
Binary{-> .next == 0.5(?.random)}.length
Since .next generates randomly, the length is a variable (infinitely generating) probability distribution.
We could, instead of a Binary, also reference an Array with arbitrary objects:
Array{-> .next == 0.5(?.random)}
There is however, a slight problem with the following subexpression:
Because we currently point to an arbitrary Array, this is any Node. In other words, it's an infinitely generating object, we can't just uniformly pick a random element from an infinitely generating object. Which is why this statement would fail. Instead, you'd have to define some other way to generate random Nodes.