100 lines
3.5 KiB
C#
100 lines
3.5 KiB
C#
using System.Diagnostics;
|
|
|
|
namespace SJK.Functional;
|
|
|
|
public static class OptionExtensions
|
|
{
|
|
public static IEnumerable<TResult> Match<T, TResult>(this IEnumerable<IOption<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 IOption<T> GetValue<Tkey, T>(this IReadOnlyDictionary<Tkey, T> value, Tkey key) where Tkey : notnull
|
|
{
|
|
if (value.TryGetValue(key, out var v))
|
|
{
|
|
return v.ToOption();
|
|
}
|
|
return None<T>.Of();
|
|
}
|
|
public static IOption<T> OrElse<T>(this IOption<T> option, Func<IOption<T>> fallback)
|
|
{
|
|
return option.Match(
|
|
some => option,
|
|
() => fallback()
|
|
);
|
|
}
|
|
public static IOption<TResult> BindUsing<TDisposable, TResult>(
|
|
this IOption<TDisposable> option,
|
|
Func<TDisposable, IOption<TResult>> func)
|
|
where TDisposable : IDisposable
|
|
{
|
|
return option.Match(
|
|
some =>
|
|
{
|
|
using (some) return func(some);
|
|
},
|
|
() => None<TResult>.Of()
|
|
);
|
|
}
|
|
|
|
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<IOption<T>> options)
|
|
{
|
|
foreach (var item in options)
|
|
{
|
|
if (item.HasValue(out var item2))
|
|
yield return item2;
|
|
}
|
|
}
|
|
// 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 IOption<T> FirstOrNone<T>(this IEnumerable<T> options) => options.Any() ? options.First().ToOption() : None<T>.Of();
|
|
public static IOption<T> FirstOrNone<T>(this IEnumerable<T> options, Predicate<T> predicate)
|
|
{
|
|
foreach (var item in options)
|
|
{
|
|
if (predicate(item))
|
|
{
|
|
return item.ToOption();
|
|
}
|
|
}
|
|
return None<T>.Of();
|
|
}
|
|
}
|