using System; using System.Runtime.Serialization; namespace ZeroLevel.Services.Extensions { /// /// Обобщенные возможности из ФП /// public static class FPCommon { /* * Func add = (x,y) => x + y; * Func> curriedAdd = add.Curry(); * Func inc = curriedAdd(1); */ /// /// Каррирование /// public static Func> Curry(this Func f) { return a => b => f(a, b); } /* * Func add = (x,y) => x + y; * Func inc = add.Partial(1); */ /// /// Частичное исполнение /// public static Func Partial(this Func f, A a) { return b => f(a, b); } /// /// PipeTo /// /* * Before * public IActionResult Get() {var someData = query.Where(x => x.IsActive).OrderBy(x => x.Id).ToArray();return Ok(someData);} * After * public IActionResult Get() => query.Where(x => x.IsActive).OrderBy(x => x.Id).ToArray().PipeTo(Ok); */ public static TResult PipeTo(this TSource source, Func func) => func(source); } public class Either { [DataMember] private readonly bool _isLeft; [DataMember] private readonly TL _left; [DataMember] private readonly TR _right; public Either(TL left) { _left = left; _isLeft = true; } public Either(TR right) { _right = right; _isLeft = false; } /// /// Checks the type of the value held and invokes the matching handler function. /// /// The return type of the handler functions. /// Handler for the Left type. /// Handler for the Right type. /// The value returned by the invoked handler function. /// /// public T Match(Func ofLeft, Func ofRight) { if (ofLeft == null) { throw new ArgumentNullException(nameof(ofLeft)); } if (ofRight == null) { throw new ArgumentNullException(nameof(ofRight)); } return _isLeft ? ofLeft(_left) : ofRight(_right); } /// /// Checks the type of the value held and invokes the matching handler function. /// /// Handler for the Left type. /// Handler for the Right type. /// /// public void Match(Action ofLeft, Action ofRight) { if (ofLeft == null) { throw new ArgumentNullException(nameof(ofLeft)); } if (ofRight == null) { throw new ArgumentNullException(nameof(ofRight)); } if (_isLeft) { ofLeft(_left); } else { ofRight(_right); } } public TL LeftOrDefault() => Match(l => l, r => default(TL)); public TR RightOrDefault() => Match(l => default(TR), r => r); public Either Swap() => Match(Right, Left); public Either Bind(Func f) => BindMany(x => Right(f(x))); public Either BindMany(Func> f) => Match(Left, f); public Either BindMany(Func> f, Func selector) => BindMany(x => f(x).Bind(t => selector(_right, t))); public static implicit operator Either(TL left) => new Either(left); public static implicit operator Either(TR right) => new Either(right); public static Either Left(TLeft left) => new Either(left); public static Either Right(TRight right) => new Either(right); public static Either Try(Func f) { try { return new Either(f.Invoke()); } catch (Exception ex) { return new Either(ex); } } } }