Suppose a lazy value holds an integer, and the next function returns a lazy result. Mapping that function produces `Lazy<Lazy<R>>`: two layers where the workflow needs one. Bind applies a context-producing function and returns a single contextual result instead. section 11.3
Its shape is `Bind(M<T> value, Func<T, M<R>> function) → M<R>`. The result keeps the capability supplied by `M` while preserving what the function does. For nullable values, Bind skips the function when no value exists; for lazy values, it delays the work; for tasks, it awaits both stages; for sequences, it concatenates the sequences produced for each item. section 11.3
static Nullable<R> Bind<T, R>(Nullable<T> x, Func<T, Nullable<R>> func)
where T : struct, R : struct =>
x.HasValue ? func(x.Value) : null;
static Lazy<R> Bind<T, R>(Lazy<T> x, Func<T, Lazy<R>> func) =>
new Lazy<R>(() => func(x.Value).Value);
async static Task<R> Bind<T, R>(Task<T> x, Func<T, Task<R>> func) =>
await func(await x);
static IEnumerable<R> Bind<T, R>(IEnumerable<T> x,
Func<T, IEnumerable<R>> func)
{
foreach(T t in x)
foreach(R r in func(t))
yield return r;
}
Compare the four implementations: each handles its own context, so callers can chain context-producing functions without handling a nested wrapper. section 11.3
For sequences, Bind is called `SelectMany` in C# and `flatMap` in Python and Java. Unlike `Select` (Map), it takes a function that returns a sequence for each input and yields their elements as one sequence. This also makes filtering expressible through Bind: produce a one-item sequence when a predicate succeeds, or an empty one when it fails. That version works, but allocates many tiny sequences. section 11.4
Binding a likelihood to a prior
A discrete distribution is another context. Bind treats its input as a prior distribution and the supplied function as a likelihood, then forms a joint distribution and projects its marginal. With a 10% prior probability of a cold and different sneezing probabilities depending on whether a cold is present, `prior.Bind(SneezedGivenCold)` gives sneezing weights of 113 for yes and 887 for no. section 14.1
Bind and Unit, which wraps a plain value, are enough to derive two related operations: `Map(x, f) = Bind(x, t => Unit(f(t)))` applies a plain-value function, while `Join(x) = Bind(x, inner => inner)` removes one wrapper layer. For distributions, Join can flatten a coin-flip choice between two dice distributions into one distribution of die results. section 11.3 section 14.1




