/// <summary> /// Either constructor /// Constructs an Either in a Right state /// </summary> /// <typeparam name="L">Left</typeparam> /// <typeparam name="R">Right</typeparam> /// <param name="value">Right value</param> /// <returns>A new Either instance</returns> public static Either <L, R> Right <L, R>(R value) => Either <L, R> .Right(value);
/// <summary> /// Subtract the Right of one either from the Right of another /// For numeric values the behaviour is to find the difference between the Rights (lhs - rhs) /// For Lst values the behaviour is to remove items in the rhs from the lhs /// For Map or Set values the behaviour is to remove items in the rhs from the lhs /// Otherwise if the R type derives from ISubtractable then the behaviour /// is to call lhs.Subtract(rhs); /// </summary> /// <typeparam name="L">Left</typeparam> /// <typeparam name="R">Right</typeparam> /// <param name="lhs">Left-hand side of the operation</param> /// <param name="rhs">Right-hand side of the operation</param> /// <returns>lhs - rhs</returns> public static Either <L, R> subtract <L, R>(Either <L, R> lhs, Either <L, R> rhs) => lhs.Subtract(rhs);
/// <summary> /// Maps the value in the Either if it's in a Right state /// </summary> /// <typeparam name="L">Left</typeparam> /// <typeparam name="R">Right</typeparam> /// <typeparam name="Ret">Mapped Either type</typeparam> /// <param name="either">Either to map</param> /// <param name="mapper">Map function</param> /// <returns>Mapped Either</returns> public static Either <Ret, R> mapLeft <L, R, Ret>(Either <L, R> either, Func <L, Ret> mapper) => either.MapLeft(mapper);
/// <summary> /// Invokes a predicate on the value of the Either if it's in the Right state /// </summary> /// <typeparam name="L">Left</typeparam> /// <typeparam name="R">Right</typeparam> /// <param name="self">Either to forall</param> /// <param name="Right">Right predicate</param> /// <param name="Left">Left predicate</param> /// <returns>True if the predicate returns True. True if the Either is in a bottom state.</returns> public static bool forall <L, R>(Either <L, R> either, Func <R, bool> Right, Func <L, bool> Left) => either.ForAll(Right, Left);
/// <summary> /// Invokes a predicate on the value of the Either if it's in the Right state /// </summary> /// <typeparam name="L">Left</typeparam> /// <typeparam name="R">Right</typeparam> /// <param name="either">Either to check existence of</param> /// <param name="pred">Predicate</param> /// <returns>True if the Either is in a Right state and the predicate returns True. False otherwise.</returns> public static bool exists <L, R>(Either <L, R> either, Func <L, bool> pred) => either.Exists(pred);
/// <summary> /// Apply Either values to an Either function of arity 2 /// </summary> /// <param name="self">Either function</param> /// <param name="arg1">Either argument</param> /// <param name="arg2">Either argument</param> /// <returns>Returns the result of applying the optional arguments to the optional function</returns> public static Either <L, R> apply <L, T1, T2, R>(Either <L, Func <T1, T2, R> > either, Either <L, T1> arg1, Either <L, T2> arg2) => either.Apply(arg1, arg2);
/// <summary> /// Folds the either into an S /// https://en.wikipedia.org/wiki/Fold_(higher-order_function) /// </summary> /// <typeparam name="S">State</typeparam> /// <typeparam name="L">Left</typeparam> /// <typeparam name="R">Right</typeparam> /// <param name="self">Either to fold</param> /// <param name="state">Initial state</param> /// <param name="Right">Right fold function</param> /// <param name="Left">Left fold function</param> /// <returns>Folded state</returns> public static S fold <L, R, S>(Either <L, R> either, S state, Func <S, R, S> Right, Func <S, L, S> Left) => either.Fold(state, Right, Left);
/// <summary> /// Returns the rightValue if the Either is in a Left state. /// Returns the Right value if the Either is in a Right state. /// </summary> /// <param name="rightValue">Value to return if in the Left state</param> /// <returns>Returns an unwrapped Right value</returns> public static R ifLeft <L, R>(Either <L, R> either, R rightValue) => either.IfLeft(rightValue);
/// <summary> /// Executes the Left action if the Either is in a Left state. /// </summary> /// <param name="Left">Function to generate a Right value if in the Left state</param> /// <returns>Returns an unwrapped Right value</returns> public static Unit ifLeft <L, R>(Either <L, R> either, Action <L> Left) => either.IfLeft(Left);
/// <summary> /// Executes the Left function if the Either is in a Left state. /// Returns the Right value if the Either is in a Right state. /// </summary> /// <param name="Left">Function to generate a Right value if in the Left state</param> /// <returns>Returns an unwrapped Right value</returns> public static R ifLeft <L, R>(Either <L, R> either, Func <R> Left) => either.IfLeft(Left);
/// <summary> /// Executes the leftMap function if the Either is in a Left state. /// Returns the Right value if the Either is in a Right state. /// </summary> /// <param name="leftMap">Function to generate a Right value if in the Left state</param> /// <returns>Returns an unwrapped Right value</returns> public static R ifLeft <L, R>(Either <L, R> either, Func <L, R> leftMap) => either.IfLeft(leftMap);
/// <summary> /// Either constructor from Nullable /// Constructs an Either in a Left state or throws a ValueIsNullException if the value is null /// </summary> /// <typeparam name="L">Left</typeparam> /// <typeparam name="R">Right</typeparam> /// <param name="value">Left value</param> /// <returns>A new Either instance</returns> public static Either <L, R> Left <L, R>(L?value) where L : struct => isnull(value) ? raise <Either <L, R> >(new ValueIsNullException()) : Either <L, R> .Left(value.Value);
/// <summary> /// Either constructor from Nullable /// Constructs an Either in a Right state or throws a ValueIsNullException if the value is null /// </summary> /// <typeparam name="L">Left</typeparam> /// <typeparam name="R">Right</typeparam> /// <param name="value">Right value</param> /// <returns>A new Either instance</returns> public static Either <L, R> Right <L, R>(R?value) where R : struct => isnull(value) ? raise <Either <L, R> >(new ValueIsNullException()) : Either <L, R> .Right(value.Value);
/// <summary> /// Either constructor /// Constructs an Either in a Left state /// </summary> /// <typeparam name="L">Left</typeparam> /// <typeparam name="R">Right</typeparam> /// <param name="value">Left value</param> /// <returns>A new Either instance</returns> public static Either <L, R> Left <L, R>(L value) => Either <L, R> .Left(value);
/// <summary> /// Apply an Either value to an Either function /// </summary> /// <param name="either">Either function</param> /// <param name="arg">Either argument</param> /// <returns>Returns the result of applying the Either argument to the Either function</returns> public static Either <L, Res> apply <L, R, Res>(Either <L, Func <R, Res> > either, Either <L, R> arg) => either.Apply(arg);
/// <summary> /// Invokes the Right action if the Either is in a Right state, otherwise does nothing /// </summary> /// <param name="Right">Action to invoke</param> /// <returns>Unit</returns> public static Unit ifRight <L, R>(Either <L, R> either, Action <R> Right) => either.IfRight(Right);
/// <summary> /// Apply an Either value to an Either function of arity 2 /// </summary> /// <param name="self">Either function</param> /// <param name="arg">Either argument</param> /// <returns>Returns the result of applying the Either argument to the Either function: /// an Either function of arity 1</returns> public static Either <L, Func <T2, R> > apply <L, T1, T2, R>(Either <L, Func <T1, T2, R> > either, Either <L, T1> arg) => either.Apply(arg);
/// <summary> /// Returns the leftValue if the Either is in a Right state. /// Returns the Left value if the Either is in a Left state. /// </summary> /// <param name="leftValue">Value to return if in the Left state</param> /// <returns>Returns an unwrapped Left value</returns> public static L ifRight <L, R>(Either <L, R> either, L leftValue) => either.IfRight(leftValue);
/// <summary> /// Folds the either into an S /// https://en.wikipedia.org/wiki/Fold_(higher-order_function) /// </summary> /// <typeparam name="S">State</typeparam> /// <typeparam name="L">Left</typeparam> /// <typeparam name="R">Right</typeparam> /// <param name="either">Either to fold</param> /// <param name="state">Initial state</param> /// <param name="folder">Fold function</param> /// <returns>Folded state</returns> public static S fold <S, L, R>(Either <L, R> either, S state, Func <S, L, S> folder) => either.Fold(state, folder);
/// <summary> /// Returns the result of Left() if the Either is in a Right state. /// Returns the Left value if the Either is in a Left state. /// </summary> /// <param name="Left">Function to generate a Left value if in the Right state</param> /// <returns>Returns an unwrapped Left value</returns> public static L ifRight <L, R>(Either <L, R> either, Func <L> Left) => either.IfRight(Left);
/// <summary> /// Invokes a predicate on the value of the Either if it's in the Right state /// </summary> /// <typeparam name="L">Left</typeparam> /// <typeparam name="R">Right</typeparam> /// <param name="either">Either to forall</param> /// <param name="pred">Predicate</param> /// <returns>True if the Either is in a Left state. /// True if the Either is in a Right state and the predicate returns True. /// False otherwise.</returns> public static bool forall <L, R>(Either <L, R> either, Func <L, bool> pred) => either.ForAll(pred);
/// <summary> /// Returns the result of leftMap if the Either is in a Right state. /// Returns the Left value if the Either is in a Left state. /// </summary> /// <param name="leftMap">Function to generate a Left value if in the Right state</param> /// <returns>Returns an unwrapped Left value</returns> public static L ifRight <L, R>(Either <L, R> either, Func <R, L> leftMap) => either.IfRight(leftMap);
/// <summary> /// Counts the Either /// </summary> /// <typeparam name="L">Left</typeparam> /// <typeparam name="R">Right</typeparam> /// <param name="either">Either to count</param> /// <returns>1 if the Either is in a Right state, 0 otherwise.</returns> public static int count <L, R>(Either <L, R> either) => either.Count();
/// <summary> /// Invokes the Right or Left function depending on the state of the Either provided /// </summary> /// <typeparam name="L">Left</typeparam> /// <typeparam name="R">Right</typeparam> /// <typeparam name="Ret">Return type</typeparam> /// <param name="either">Either to match</param> /// <param name="Right">Function to invoke if in a Right state</param> /// <param name="Left">Function to invoke if in a Left state</param> /// <returns>The return value of the invoked function</returns> public static Ret match <L, R, Ret>(Either <L, R> either, Func <R, Ret> Right, Func <L, Ret> Left) => either.Match(Right, Left);
/// <summary> /// Invokes a predicate on the value of the Either /// </summary> /// <typeparam name="L">Left</typeparam> /// <typeparam name="R">Right</typeparam> /// <param name="self">Either to check existence of</param> /// <param name="Right">Right predicate</param> /// <param name="Left">Left predicate</param> /// <returns>True if the predicate returns True. False otherwise or if the Either is in a bottom state.</returns> public static bool exists <L, R>(Either <L, R> either, Func <R, bool> Right, Func <L, bool> Left) => either.Exists(Right, Left);
/// <summary> /// Append the Right of one either to the Right of another /// For numeric values the behaviour is to sum the Rights (lhs + rhs) /// For string values the behaviour is to concatenate the strings /// For Lst/Stck/Que values the behaviour is to concatenate the lists /// For Map or Set values the behaviour is to merge the sets /// Otherwise if the R type derives from IAppendable then the behaviour /// is to call lhs.Append(rhs); /// </summary> /// <typeparam name="L">Left</typeparam> /// <typeparam name="R">Right</typeparam> /// <param name="lhs">Left-hand side of the operation</param> /// <param name="rhs">Right-hand side of the operation</param> /// <returns>lhs + rhs</returns> public static Either <L, R> append <L, R>(Either <L, R> lhs, Either <L, R> rhs) => lhs.Append(rhs);
/// <summary> /// Maps the value in the Either if it's in a Right state /// </summary> /// <typeparam name="L">Left</typeparam> /// <typeparam name="R">Right</typeparam> /// <typeparam name="Ret">Mapped Either type</typeparam> /// <param name="either">Either to map</param> /// <param name="mapper">Map function</param> /// <returns>Mapped Either</returns> public static Either <L, Ret> map <L, R, Ret>(Either <L, R> either, Func <R, Ret> mapper) => either.Map(mapper);
/// <summary> /// Invokes the Right or Left action depending on the state of the Either provided /// </summary> /// <typeparam name="L">Left</typeparam> /// <typeparam name="R">Right</typeparam> /// <param name="either">Either to match</param> /// <param name="Right">Action to invoke if in a Right state</param> /// <param name="Left">Action to invoke if in a Left state</param> /// <returns>Unit</returns> public static Unit match <L, R>(Either <L, R> either, Action <R> Right, Action <L> Left) => either.Match(Right, Left);
/// <summary> /// Bi-maps the value in the Either if it's in a Right state /// </summary> /// <typeparam name="L">Left</typeparam> /// <typeparam name="R">Right</typeparam> /// <typeparam name="LRet">Left return</typeparam> /// <typeparam name="RRet">Right return</typeparam> /// <param name="self">Either to map</param> /// <param name="Right">Right map function</param> /// <param name="Left">Left map function</param> /// <returns>Mapped Either</returns> public static Either <LRet, RRet> bimap <L, R, LRet, RRet>(Either <L, R> either, Func <R, RRet> Right, Func <L, LRet> Left) => either.BiMap(Right, Left);
public static Either <L, Either <L, B> > Sequence <L, A, B>(this Either <L, A> ta, Func <A, Either <L, B> > f) => ta.Map(f).Sequence();