Files
SjkScripts/Functional/OptionExtensions.cs
ronnie 262b76c4d5
All checks were successful
Build NuGet / build (push) Successful in 1m43s
Refactored Option<T> to have opertator lifting and removed ref struct for now.
2026-08-07 12:58:11 -04:00

179 lines
7.3 KiB
C#

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