A monad is a generic type that adds a capability—such as nullability, laziness, asynchrony, or sequencing—while preserving the workflow of operations on the underlying value. section 11.0 section 11.1
Unit lifts an ordinary value into a monadic wrapper. Bind chains a function that already returns a monadic value, preventing incompatible capabilities from becoming unnecessarily nested. section 11.1 section 11.3
The core operations expose the common structure across different generic types:
- Unit wraps a value in Nullable<T>, Lazy<T>, Task<T>, or a one-element IEnumerable<T>. section 11.1
- Map applies an ordinary function while preserving the existing capability. section 11.3
- Bind chains a monad-returning function, with implementations for nullable values, laziness, tasks, and sequences. section 11.3
- Join removes one level of nested monadic structure; sequence monads expose Bind and Map as SelectMany and Select. section 11.5
Keeping laziness from nesting
Given a Lazy<int> and a function returning Lazy<double>, ordinary Map produces Lazy<Lazy<double>>. Bind instead evaluates the outer workflow and returns a single Lazy<double>, preserving one layer of laziness.
static Nullable<T> NullableUnit<T> where T : struct (T t) =>
new Nullable<T>(t);
static Lazy<T> LazyUnit<T>(T t) => new Lazy<T>(t);
static Task<T> TaskUnit<T>(T t) => Task.FromResult(t);
static IEnumerable<T> SeqUnit<T>(T t) => [ t ];
Compare compact C# Unit implementations for nullable values, lazy values, tasks, and sequences. section 11.1





