#region Validation - Functional Extension Methods
public static partial class ƒ {
#region Validation - Fold
public static R2 Fold<L, R1, R2>(this Validation<L, R1> e, Func<List<L>, R2> l, Func<R1, R2> r) {
switch (e.state) {
case ValidationState.Right:
return r(e.right);
default:
return l(e.left);
}
}
#endregion
#region Validation - Functor
public static Validation<L, R2> MapR<L, R1, R2>(this Func<R1, R2> fn, Validation<L, R1> e) {
return e.MapR(fn);
}
public static Validation<L, R2> MapR<L, R1, R2>(this Validation<L, R1> e, Func<R1, R2> fn) {
switch (e.state) {
case ValidationState.Right:
return Validation<L, R2>.Right(fn(e.right));
default:
return Validation<L, R2>.Left(e.left);
}
}
#endregion
#region Validation - Monad
public static Validation<L, R2> FlatMap<L, R1, R2>(this Validation<L, R1> e, Func<R1, Validation<L, R2>> fn) {
switch (e.state) {
case ValidationState.Right:
return fn(e.right);
default:
return Validation<L, R2>.Left(e.left);
}
}
public static Validation<L, R2> FlatMap<L, R1, R2>(this Func<R1, Validation<L, R2>> fn, Validation<L, R1> e) {
return e.FlatMap(fn);
}
#endregion
#region Validation - Applicative Functor
public static Validation<L, R2> Apply<L, R1, R2>(this Validation<L, R1> e, Validation<L, Func<R1, R2>> fn) {
switch ((a: fn.isRight, b: e.isRight)) {
case var t when t.And(true, true):
return fn.FlatMap(g => e.MapR(x => g(x)));
case var t when t.And(false, false):
fn.left.AddRange(e.left);
return Validation<L, R2>.Left(fn.left);
case var t when t.First(false):
return Validation<L, R2>.Left(fn.left);
default:
return Validation<L, R2>.Left(e.left);
}
}
public static Validation<L, R2> Apply<L, R1, R2>(this Validation<L, Func<R1, R2>> fn, Validation<L, R1> e) {
return e.Apply(fn);
}
public static Validation<L, R> ToValidation<L, R>(this R r) {
return Validation<L, R>.Right(r);
}
#endregion
#region Validation - Applicative Functor - Lift a function & actions
public static Validation<L, R> LiftA<A, L, R>(this Func<A, R> fn, Validation<L, A> a) {
return fn.MapR(a);
}
public static Validation<L, R> LiftA<A, B, L, R>(this Func<A, B, R> fn, Validation<L, A> a, Validation<L, B> b) {
return fn.Curry().MapR(a).Apply(b);
}
public static Validation<L, R> LiftA<A, B, C, L, R>(this Func<A, B, C, R> fn, Validation<L, A> a, Validation<L, B> b, Validation<L, C> c) {
return fn.Curry().MapR(a).Apply(b).Apply(c);
}
public static Validation<L, R> LiftA<A, B, C, D, L, R>(this Func<A, B, C, D, R> fn, Validation<L, A> a, Validation<L, B> b, Validation<L, C> c, Validation<L, D> d) {
return fn.Curry().MapR(a).Apply(b).Apply(c).Apply(d);
}
public static Validation<L, R> LiftA<A, B, C, D, E, L, R>(this Func<A, B, C, D, E, R> fn, Validation<L, A> a, Validation<L, B> b, Validation<L, C> c, Validation<L, D> d, Validation<L, E> e) {
return fn.Curry().MapR(a).Apply(b).Apply(c).Apply(d).Apply(e);
}
public static Validation<L, R> LiftA<A, B, C, D, E, F, L, R>(this Func<A, B, C, D, E, F, R> fn, Validation<L, A> a, Validation<L, B> b, Validation<L, C> c, Validation<L, D> d, Validation<L, E> e, Validation<L, F> f) {
return fn.Curry().MapR(a).Apply(b).Apply(c).Apply(d).Apply(e).Apply(f);
}
public static Validation<L, R> LiftA<A, B, C, D, E, F, G, L, R>(this Func<A, B, C, D, E, F, G, R> fn, Validation<L, A> a, Validation<L, B> b, Validation<L, C> c, Validation<L, D> d, Validation<L, E> e, Validation<L, F> f, Validation<L, G> g) {
return fn.Curry().MapR(a).Apply(b).Apply(c).Apply(d).Apply(e).Apply(f).Apply(g);
}
public static Validation<L, R> LiftA<A, B, C, D, E, F, G, H, L, R>(this Func<A, B, C, D, E, F, G, H, R> fn, Validation<L, A> a, Validation<L, B> b, Validation<L, C> c, Validation<L, D> d, Validation<L, E> e, Validation<L, F> f, Validation<L, G> g, Validation<L, H> h) {
return fn.Curry().MapR(a).Apply(b).Apply(c).Apply(d).Apply(e).Apply(f).Apply(g).Apply(h);
}
public static Validation<L, R> LiftA<A, B, C, D, E, F, G, H, I, L, R>(this Func<A, B, C, D, E, F, G, H, I, R> fn, Validation<L, A> a, Validation<L, B> b, Validation<L, C> c, Validation<L, D> d, Validation<L, E> e, Validation<L, F> f, Validation<L, G> g, Validation<L, H> h, Validation<L, I> i) {
return fn.Curry().ToValidation<L, Func<A, Func<B, Func<C, Func<D, Func<E, Func<F, Func<G, Func<H, Func<I, R>>>>>>>>>>().Apply(a).Apply(b).Apply(c).Apply(d).Apply(e).Apply(f).Apply(g).Apply(h).Apply(i);
}
public static Validation<L, R> LiftA<A, B, C, D, E, F, G, H, I, J, L, R>(this Func<A, B, C, D, E, F, G, H, I, J, R> fn, Validation<L, A> a, Validation<L, B> b, Validation<L, C> c, Validation<L, D> d, Validation<L, E> e, Validation<L, F> f, Validation<L, G> g, Validation<L, H> h, Validation<L, I> i, Validation<L, J> j) {
return fn.Curry().ToValidation<L, Func<A, Func<B, Func<C, Func<D, Func<E, Func<F, Func<G, Func<H, Func<I, Func<J, R>>>>>>>>>>>().Apply(a).Apply(b).Apply(c).Apply(d).Apply(e).Apply(f).Apply(g).Apply(h).Apply(i).Apply(j);
}
#endregion
#region Validation - Match
public static void Match<L, R>(this Validation<L, R> e, Action<List<L>> left, Action<R> right) {
switch (e.state) {
case ValidationState.Right:
right(e.right);
return;
default:
left(e.left);
return;
}
}
#endregion
#region Print
public static void Print<L, R>(this Validation<L, R> e, string title = "") {
Console.WriteLine("{0} ---> Validation[{1}]", title, e.Fold(
l => string.Format("Left: '{0}'", l.Fold("", (ai, ei) => ai + ei + ",").DropLast(1)),
r => string.Format("Right: {0}", r)
));
}
#endregion
}
#endregion