using System;
using System.Runtime.Serialization;
namespace ZeroLevel.Services.Extensions
{
///
/// FP
///
public static class FPCommon
{
/*
* Func add = (x,y) => x + y;
* Func> curriedAdd = add.Curry();
* Func inc = curriedAdd(1);
*/
///
/// Currying
///
public static Func> Curry(this Func f)
{
return a => b => f(a, b);
}
/*
* Func add = (x,y) => x + y;
* Func inc = add.Partial(1);
*/
///
/// Partial currying
///
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);
}
}
}
}