Either and Unit
Package Trax.CoreNamespace Trax.Core.FunctionalSource Either.cs, Unit.cs
Either<TLeft, TRight> is a value on one of two tracks: Left, which a train uses for the exception that switched it to the failure track, or Right, the result. Junctions() returns Task<Either<Exception, TReturn>> and RunEither hands it to the caller. Unit is the value of a junction or train that produces nothing.
Signatures
namespace Trax.Core.Functional;
public enum EitherStatus : byte
{
IsBottom = 0,
IsLeft = 1,
IsRight = 2,
}
public readonly struct Either<TLeft, TRight> : IEquatable<Either<TLeft, TRight>>
{
public EitherStatus State { get; }
public bool IsLeft { get; }
public bool IsRight { get; }
public bool IsBottom { get; }
public static Either<TLeft, TRight> Left(TLeft value);
public static Either<TLeft, TRight> Right(TRight value);
public static implicit operator Either<TLeft, TRight>(TLeft value);
public static implicit operator Either<TLeft, TRight>(TRight value);
public static explicit operator TRight(Either<TLeft, TRight> either);
public static explicit operator TLeft(Either<TLeft, TRight> either);
public TResult Match<TResult>(Func<TRight, TResult> Right, Func<TLeft, TResult> Left, Func<TResult>? Bottom = null);
public void Match(Action<TRight> Right, Action<TLeft> Left, Action? Bottom = null);
public Unit IfRight(Action<TRight> action);
public Unit IfLeft(Action<TLeft> action);
public Either<TRight, TLeft> Swap();
public TRight ValueUnsafe();
}
public readonly struct Unit : IComparable<Unit>, IEquatable<Unit>
{
public static readonly Unit Default;
}Members
| Member | Description |
|---|---|
State | Which side holds the value: EitherStatus.IsLeft, IsRight, or IsBottom for default(Either<TLeft, TRight>), which holds none |
IsLeft, IsRight, IsBottom | State as a flag |
Left(value), Right(value) | An Either on that side. Throw ArgumentNullException for null: neither side holds null. |
| Implicit conversions | A TLeft or a TRight converts to an Either, so a junction chain can return either one where an Either is expected |
| Explicit conversions | (TRight)either and (TLeft)either read a side, and throw InvalidCastException when the value is on the other side |
Match(Right, Left, Bottom) | Runs the function or action for the side that holds the value. Throws InvalidOperationException for a bottom value when no Bottom is given. |
IfRight(action), IfLeft(action) | Runs the action only when the value is on that side; returns Unit |
Swap() | The same value on the other side. A bottom value stays bottom. |
ValueUnsafe() | The right value, or default when the value is not on the right. Read the left value with Swap().ValueUnsafe(). |
Unit.Default | The one Unit value. Every Unit equals every other. |
Two Either values are equal when they are on the same side and their values are equal. ToString() writes Right(value), Left(value) or Bottom.
Example
using Trax.Core.Functional;
Either<Exception, int> result = 42;
var text = result.Match(Right: value => $"got {value}", Left: error => error.Message);
if (result.IsLeft)
Console.WriteLine(result.Swap().ValueUnsafe().Message);See also
- RunEither, which returns an
Either - Resolve, which ends a chain in one
- Functional programming in Trax