using System.Diagnostics; using System.Numerics; namespace SJK.Functional; public static partial class OptionExtensions { public static IEnumerable Match(this IEnumerable> values, Func onSome, Func onNone) { foreach (var item in values) { yield return item.Match(onSome, onNone); } } // public static IOption GetValue(this IDictionary value, Tkey key) where Tkey : notnull // { // if (value.TryGetValue(key, out var v)) // { // return v.ToOption(); // } // return None.Of(); // } public static Option GetValueOrNone(this IReadOnlyDictionary value, Tkey key) where Tkey : notnull { if (value.TryGetValue(key, out var v)) { return v.ToOption(); } return Option.None; } // public static Option OrElse(this Option option, Func> fallback) // { // return option.Match( // some => option, // () => fallback() // ); // } public static Option BindUsing( this Option option, Func> func) where TDisposable : IDisposable { return option.Match( some => { using (some) return func(some); }, () => Option.None ); } // public static IOption ToOption(this T? value) => value != null ? Some.Of(value) : None.Of(); // [StackTraceHidden] // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public static T OrThrow(this IOption option, Func exceptionFactory) where TEx : Exception // { // if (option.HasValue(out var value)) // return value; // throw exceptionFactory(); // } // public static IEither ToEither(this Tvalue value, Func isSuccess, Func ok, Func err) // { // return isSuccess(value) ? new Right(ok()) : new Left(err(value)); // } // public static IEither ToEither(this Tvalue value, Tvalue successValue, Func ok, Func err) where Tvalue : notnull // { // return value.ToEither(e => e.Equals(successValue), ok, err); // } // public static IEnumerable> ToOptions(this IEnumerable value) => value.Select(thing => thing.ToOption()); // public static Some ToSome(this T value) where T : notnull => Some.Of(value); // public static void IfSome(this IOption value, Action onSome) => value.Match(onSome, () => { }); // public static void IfNone(this IOption value, Action onNone) => value.Match(_ => { }, onNone); // public static T Or(this IOption value, Func @default) => value.Or(@default()); public static IEnumerable OnlySomes(this IEnumerable> options) { foreach (var item in options) { if (item.HasValue) yield return item.Value; } } // public static None ToNone(this T value) => None.Of(); // public static Option ToStructOption(this IOption option) => option.HasValue(out var value) ? Option.Some(value) : Option.None; // public static IOption ToClassOption(this Option option) => option.HasValue ? option.Value.ToOption() : None.Of(); public static Option FirstOrNone(this IEnumerable options) => options.Any() ? options.First().ToOption() : Option.None; public static Option FirstOrNone(this IEnumerable options, Predicate predicate) { foreach (var item in options) { if (predicate(item)) { return item.ToOption(); } } return Option.None; } public static Option ToOption(this T? value) => value is null ? Option.None : Option.Some(value); public static Option TryGetValue(this Option> option, T key) => option.Map(f => f.TryGetValue(key, out var result)?Option.Some(result):Option.None()); extension(Option) where T : IAdditionOperators { public static Option operator +(Option left, T right) => left.Map(f => f + right); } extension(Option) where T : ISubtractionOperators { public static Option operator -(Option left, T right) => left.Map(f => f - right); } extension(Option) where T : IMultiplyOperators { public static Option operator *(Option left, T right) => left.Map(f => f *right); } extension(Option) where T : IDivisionOperators { public static Option operator /(Option left, T right) => left.Map(f => f / right); } extension(Option) where T : IIncrementOperators { public static Option operator ++(Option left) => left.Map(f => f++); } extension(Option) where T : IDecrementOperators { public static Option operator --(Option left) => left.Map(f => f--); } extension(Option) where T : IModulusOperators { public static Option operator %(Option left, T right) => left.Map(f => f % right); } extension(Option _) where T : IShiftOperators { public static Option operator <<(Option left, T right) => left.Map(f => f << right); public static Option operator >>(Option left, T right) => left.Map(f => f >> right); public static Option operator >>>(Option left, T right) => left.Map(f => f >>> right); } extension(Option) where T : IBitwiseOperators { public static Option operator &(Option left, T right) => left.Map(f => f & right); public static Option operator |(Option left, T right) => left.Map(f => f | right); public static Option operator ^(Option left, T right) => left.Map(f => f ^ right); public static Option operator ~(Option left) => left.Map(f => ~f); } extension(Option) where T : IComparisonOperators { public static Option operator >(Option left, T right) => left.Map(f => f > right); public static Option operator <(Option left, T right) => left.Map(f => f < right); public static Option operator >=(Option left, T right) => left.Map(f => f >= right); public static Option operator <=(Option left, T right) => left.Map(f => f <= right); } extension(Option) where T : IUnaryPlusOperators { public static Option operator +(Option left) => left.Map(f => +f); } extension(Option) where T : IUnaryNegationOperators { public static Option operator -(Option left) => left.Map(f => -f); } extension(in Option option) where T : IComparable { public int CompareTo(T? value) => option.Map(f => f.CompareTo(value)); } extension(in Option option) where T : IParsable { public static Option TryParse(in string? value, IFormatProvider formatProvider) => T.TryParse(value, formatProvider, out var result)?Option.Some(result):Option.None(); public static Option Parse(in string value, IFormatProvider formatProvider) => T.Parse(value, formatProvider); } extension(Option) where T : IEqualityOperators { public static Option operator ==(Option left, T right) => left.Map(f => f == right); public static Option operator !=(Option left, T right) => left.Map(f => f != right); } }