Skip to content
David Arno edited this page Feb 17, 2020 · 2 revisions

Either<TLeft, TRight>

SuccincT.Unions.Either<TLeft, TRight>

Provides a union of types TLeft and TRight. Either contains a T1 value, or a T2 value; never both nor neither.


Construction

Instances of Either<TLeft, TRight> are either created via the overloaded constructor. Because "either" unions can be directly created, TLeft and TRight must be of sufficiently different types for the compiler to be able to choose the correct constructor.

Creation via constructors

    public Either(TLeft value)
    public Either(TRight value)

Using constructors,"either" union instances are created just like any other class:

var e1 = new Either<int, string>(1);
var e2 = new Either<int, string>("2");

Equality

Either<TLeft, TRight> provides equality via Equals and the == & != operator pair. To be equal, both eithers must have a left value and those values must be equal, or both eithers must have a right value and those values must be equal:

var a = new Either<int, string>(1);
var b = new Either<int, string>(1);
var c = new Either<int, string>(2);
var d = new Either<int, string>("2");
var e = new Either<int, string>("2");
var f = new Either<int, string>("1");

// The following expressions are all true
a == a
a == b
a != c
b != d
c != d
d == e
d != f
a.Equals(b)
d.Equals(e)

Functional Use

For details on using Succinc<T>'s own pattern pattern feature with the Either type, see Pattern matching on Either<TLeft, TRight>.

As of v8, C# itself has excellent pattern matching support built in to the language. Either<TLeft, TRight> therefore provides the following deconstruct to allow it's use with position pattern matching:

public void Deconstruct(
    out EitherState state, 
    out TLeft leftValue, 
    out TRight rightValue);

EitherState is an enum with two values, Left and Right. When state == Left, leftValue will contain the value stored in the either and rightValue will be default(TRight). When state == Right, leftValue will be default(TLeft) and rightValue will contain the value stored in the either.

This then allows an either to be pattern matched as follows:

var either = new Either<int, string>(2);

var result = either switch {
    (Left, var i, _) => $"Contains int, {i}",
    (_, _, var s) => $"Contains string, '{s}'"
};

Imperative Use

As an alternative to using an either in a functional style, its value can be directly accessed by more traditional, imperative style C# code. Five read-only properties are provided for this purpose:

IsLeft

public bool IsLeft { get; }

Returns true if the value is of TLeft; otherwise it returns false.

Left

public TLeft Left { get; }

If IsLeft is true, this will return the TLeft value held by the either. Otherwise an InvalidOperationException will be thrown.

TryLeft

public Option<TLeft> TryLeft { get; }

If IsLeft is true, this will return the TLeft value held by the either as an Some(Left). Otherwise an Option<TLeft>.None is returned.

Right

public TRight Right { get; }

If IsLeft is false, this will return the TRight value held by the "either" union. Otherwise an InvalidOperationException will be thrown.

TryRight

public Option<TRight> TryRight { get; }

If IsLeft is false, this will return the TRight value held by the either as an Some(Right). Otherwise an Option<TRight>.None is returned.

Clone this wiki locally