Either<TLeft, TRight>

Tango.Types.Either<TLeft, TRight>

This type represents an either value.

Instances of Either<TLeft, TRight> encapsulates an value of TLeft or TRight type as a container and only allow access to these values by the Match e Match2 methods.

A common use of Either<TLeft, TRight> is as an alternative to Option<T> for dealing with possible missing values. But in this case, Option<T>.None is replaced by a TLeft value which can contain real and useful information.

Convention dictates that TRight is used for success types and TLeft is used for fail.

Either values can assume two different states:

  • Left (IsLeft) - When it contains a TLeft value;

  • Right (IsRight) - When it contains a TRight value.

Properties

Name

Type

Description

IsLeft

bool

Returns true when the value is an TLeft value. Otherwise, returns false.

IsRight

bool

Returns true when the value is an TRight value. Otherwise, returns false.

Constructors

Parâmetros

Retorno

Descrição

TLeft left

Either<TLeft, TRight>

Initialize a new instance with a TLeft value.

TRight right

Either<TLeft, TRight>

Initialize a new instance with a TRight value.

Methods

Name

Parameters

Returns

Description

Match

Func<TRight,TResult> methodWhenRight

Func<TLeft, TResult> methodWhenLeft

TResult

This allows a sophisticated way to apply some method for Either<TLeft, TRight> values without having to check for the existence of a left or right value.

Match2

Either<TLeft2, TRight2> either2

Func<TRight, TRight2, T> methodWhenBothRight

Func<TRight, TLeft2, T> methodWhenRightLeft

Func<TLeft, TRight2, T> methodWhenLeftRight

Func<TLeft, TLeft2, T> methodWhenBothLeft

T

This allows a sophisticated way to apply some method for two different Either<TLeft, TRight> values without having to check for the existence of a left or right value.

Match

Action<TRight> methodWhenRight

Action<TLeft> methodWhenLeft

Unit

This allows a sophisticated way to apply some method for Either<TLeft, TRight> values without having to check for the existence of a left or right value.

Match2

Either<TLeft2, TRight2> either2

Action<TRight, TRight2> methodWhenBothRight

Action<TRight, TLeft2> methodWhenRightLeft

Action<TLeft, TRight2> methodWhenLeftRight

Action<TLeft, TLeft2> methodWhenBothLeft

T

This allows a sophisticated way to apply some method for two different Either<TLeft, TRight> values without having to check for the existence of a left or right value.

Operators Overload

Operator

Parameter

Returns

Description

Implicit cast

TLeft left

Either<TLeft, TRight>

Initialize a new instance with a TLeft value.

Implicit cast

TRight right

Either<TLeft, TRight>

Initialize a new instance with a TRight value.

Implicit cast

Either<TLeft, TRight>

Option<TLeft>

Creates an Option value by Either.Left property. The results will be Some when Either IsLeft, otherwise the results will be None.

Implicit cast

Either<TLeft, TRight>

Option<TRight>

Creates an Option value by Either.Right property. The results will be Some when Either IsRight, otherwise the results will be None.

Implicit cast

Continuation<TLeft, TRight>

Either<TLeft, TRight>

Creates an Either<TLeft, TRight> from a Continuation<TLeft, TRight> value.

Usage

You can use an Either value in so many different ways.

Creating an either value

You can use the constructor to create option values in IsLeft or IsRight states, according its parameter.

Constructors

Either<bool, int> valueWithRight = new Either<bool, int>(10); //-> IsRight
Either<bool, int> valueWithLeft = new Either<bool, int>(false); //-> IsLeft

You can also use the implict cast feature. Because of it you don't need to worry about any kind of syntax, you just create the value as regular types.

Implict cast

Either<bool, int> valueWithRight = 10;   //-> IsRight
Either<bool, int> valueWithLeft = false; //-> IsLeft

Through this implicit cast you can creates new option values by using regular return commands, in this particular case is very common to use two different return commands with different types.

See the code bellow:

private Either<string, int> GetSquareIfEven(int value)
{
  if (value % 2 == 0)
    return value * value;
  else
    return "Odd";
}

It can looks weird at first, by having two returns with two different types, but actually both returns will creates a new Either value.

But instead of deal with it, Tango pass this responsibility to C#.

Getting value from an either

As Option values it is necessary to use the Match and Match2 methods to get the encapsulated value of an Either type.

In this type you can also get the value by an implicit cast to an Option of either TLeft or TRight. In this particular case the option value will receive one of these two types and creates an value according to the Either value.

With this implementation is obrigatory to properly handle with all cases about an Either value.

Implict cast to an Option

Either<bool, int> eitherValue = 10;
Option<int> optionValue = eitherValue;

//optionValue.IsSome = true
Either<bool, int> eitherValue = 10;
Option<bool> optionValue = eitherValue;

//optionValue.IsSome = false
//optionValue.IsNone = true

WARNING

Even when the implicit cast was made for the correct type the option value can receive an None value, because the restrictions of option value.

This case will occurs when the Either encapsulated value is equals to null or its default.

Either<bool, int> eitherValue = 0;
Option<int> optionValue = eitherValue;

//optionValue.IsSome = false
//optionValue.IsNone = true

You can also uses the Match method. This method receive two different functions as parameters, one for each case: Right and Left states.

Match with named parameters

Either<bool, int> eitherValue = 10;
int value = eitherValue.Match(
        methodWhenRight: number => number,
        methodWhenLeft: boolean => 0);

//value = 10

The first method is executed when the either IsRight, because of it, this method receive a TRight value as parameter (int in this example).

The second method is executed when the either IsLeft, because of it, this method receive a TLeft value as parameter (bool in this example).

These two functions are just regular parameters, so, you can omit the its names.

Match

Either<bool, int> eitherValue = 10;
int value = eitherValue.Match(
        number => number,
        boolean => 0);

//value = 10

Besides that, you can also apply some transformation in value before got it, like square the value:

Either<bool, int> eitherValue = 10;
int value = eitherValue.Match(
        number => number * number,
        boolean => 0);

//value = 100

You can also returns any value in IsLeft state, in the previous examples were used the zero value, but it isn't obrigatory.

The Match method can creates any type of value, even types that are not defined as TLeft or TRight.

Match to create a new result

Either<bool, int> eitherValue = 10;
string value = eitherValue.Match(
        number => number.ToString(),
        boolean => boolean.ToString());

//value = "10"
Either<bool, int> eitherValue = false;
string value = eitherValue.Match(
        number => number.ToString(),
        boolean => boolean.ToString());

//value = "false"

Sometimes is necessary compare more than one Either values, this type provides the Match2 method to compare two different values instead of just one.

This method is so much more complex compared to the previous one, this time, you will have to handle all possible situations.

Match2 when both Either values are in IsRight state

Either<bool, int> either = 15;
Either<bool, int> either2 = 10;
int result =
    either.Match2(
                  either2,
                  (value1, value2) => value1 + value2,
                  (value1, value2) => value1,
                  (value1, value2) => value2,
                  (value1, value2) => 0
                );
//result = 25

In the previous sample, a sum of two different Either values was made. In this particular case, both Either was in IsRight state, so the first method was executed:

(value1, value2) => value1 + value2

In this anonymous method the value1 parameter received the value from either (10) and value2 from either2(15), resulting 25.

The other three methods are executed depending on state of each Either values.

Match2 with IsRight and IsLeft, respectively

Either<bool, int> either = 15;
Either<bool, int> either2 = true;
int result =
    either.Match2(
                  either2,
                  (value1, value2) => value1 + value2,
                  (value1, value2) => value1, // -> Selected
                  (value1, value2) => value2,
                  (value1, value2) => 0
                );
//result = 15

Match2 when IsLeft and IsRight, respectively

Either<bool, int> either = false;
Either<bool, int> either2 = 10;
int result =
    either.Match2(
                  either2,
                  (value1, value2) => value1 + value2,
                  (value1, value2) => value1, 
                  (value1, value2) => value2, // -> Selected
                  (value1, value2) => 0
                );
//result = 10

Match2 when both Either values are in IsLeft state

Either<bool, int> either = false;
Either<bool, int> either2 = true;
int result =
    either.Match2(
                  either2,
                  (value1, value2) => value1 + value2,
                  (value1, value2) => value1,
                  (value1, value2) => value2,
                  (value1, value2) => 0 // -> Selecionado
                );
//result = 0

There's an overload of Match and Match2 methods to receive an Action as parameter instead of a Func.

The fundamentals about Either values can be find in Fundamentals > Either Values section.

Last updated