public delegate T IMaybe<out T>();
public static class Maybe
public static IMaybe<T> Return<T>(T x)
public static IMaybe<T> Nothing<T>()
throw new InvalidOperationException("Нельзя получить значение");
public static IMaybe<TResult> Bind<TArg, TResult>(this IMaybe<TArg> maybe, Func<TArg, IMaybe<TResult>> func)
return () => func(maybe())();
public static IMaybe<TResult> Select<TArg, TResult>(this IMaybe<TArg> maybe, Func<TArg, TResult> func)
return maybe.Bind(value => Return(func(value)));
public static IMaybe<T> Where<T>(this IMaybe<T> maybe, Func<T, bool> predicate)
return maybe.Bind(x => predicate(x) ? Return(x) : Nothing<T>());
public static IMaybe<TC> SelectMany<TA, TB, TC>(this IMaybe<TA> ma, Func<TA, IMaybe<TB>> maybeSelector, Func<TA, TB, TC> resultSelector)
return ma.Bind(a => maybeSelector(a).Select(b => resultSelector(a, b)));
public static void Main()
var one = Maybe.Return(1);
var nothing = Maybe.Nothing<int>();
var two = one.Where(z => z > 0).Select(z => z + 1);
Console.WriteLine(one());
Console.WriteLine(two());
Console.WriteLine(nothing2());