/// <summary> /// Retuns the current option only if its value matches the specified predicate. Otherwise returns an empty option. /// </summary> public static IOption <A> Where <A>(this IOption <A> option, Func <A, bool> predicate) { return(option.FlatMap(a => predicate(a).Match( t => option, f => Option.Empty <A>() ))); }
private static void HandlingNestedOptionsWithFlatMap(decimal number, decimal firstDivisor, decimal secondDivisor) { IOption <decimal> divisionResult = Divide(number, firstDivisor); IOption <IOption <decimal> > resultOfDoubleDivision = divisionResult.Map(r => Divide(r, secondDivisor)); // This option has value if both the inner and the outer option have value. IOption <decimal> flattenedResultOfDoubleDivision1 = resultOfDoubleDivision.Flatten(); // Same can be done with 1 call. IOption <decimal> flattenedResultOfDoubleDivision2 = divisionResult.FlatMap(r => Divide(r, secondDivisor)); }
/// <summary> /// Creates a new interval with the specified bounds. /// </summary> public Interval <A> Interval(IOption <IntervalBound <A> > lowerBound, IOption <IntervalBound <A> > upperBound) { if (lowerBound.IsEmpty && upperBound.IsEmpty) { return(UnboundedInterval); } if (lowerBound.FlatMap(l => upperBound.Map(u => Greater(l.Value, u.Value) || Equals(l.Value, u.Value) && (l.IsOpen || u.IsOpen))).GetOrFalse()) { return(EmptyInterval); } return(new Interval <A>(lowerBound, upperBound, isEmpty: false)); }
/// <summary> /// Turns the option of nullable into an option. /// </summary> public static IOption <A> Flatten <A>(this IOption <A?> option) where A : struct { return(option.FlatMap(a => a.ToOption())); }
/// <summary> /// Returns the value of the outer option or an empty opion. /// </summary> public static IOption <A> Flatten <A>(this IOption <IOption <A> > option) { return(option.FlatMap(o => o)); }
/// <summary> /// Maps the current value to a new option using the specified function and combines values of both of the options. /// </summary> public static IOption <B> SelectMany <A, X, B>(this IOption <A> option, Func <A, IOption <X> > f, Func <A, X, B> compose) { return(option.FlatMap(a => f(a).Map(x => compose(a, x)))); }
/// <summary> /// Maps value of the current option (if present) into a new option using the specified function and /// returns that new option. /// </summary> public static IOption <B> SelectMany <A, B>(this IOption <A> option, Func <A, IOption <B> > f) { return(option.FlatMap(f)); }
/// <summary> /// Returns whther one interval bound complements another (i.e. have same value, but differ in type). /// </summary> private bool Complements(IOption <IntervalBound <A> > a, IOption <IntervalBound <A> > b) { return(a.FlatMap(x => b.Map(y => Equals(x.Value, y.Value) && !Equals(x.Type, y.Type))).GetOrFalse()); }
/// <summary> /// Returns whether the first upper bound is less than the second. /// </summary> private bool UpperBoundLess(IOption <IntervalBound <A> > a, IOption <IntervalBound <A> > b) { var result = a.FlatMap(x => b.Map(y => Less(x.Value, y.Value) || Equals(x.Value, y.Value) && x.IsOpen && y.IsClosed)); return(result.GetOrElse(_ => a.NonEmpty && b.IsEmpty)); }