Choice
This monad, also known as Either in some other languages, allows to choose one of two (or more) inner types to return from a given method. It may sound weird at first but consider the following scenario: a given user can choose to log in by using an e-mail or a identifier. Whatever the choice once identified the user’s password will be required.
Let’s see how Choice<T1, T2, T3> can help.
public Option<User> GetUser(string input)
{
    Choice<Email, Identifier, InvalidKey> key = ExtractKey(input);
    return key switch
    {
        Email => users.GetByEmail(key),
        Identifier => users.GetByIdentifier(key),
        InvalidKey => Option.None<User>()
    }
}The method ExtractKey will try to convert the input to one of the two valid identifiers and if it couldn’t it will return a type to express it. Then once with a valid key it will try to get the user identifier and perform the search for it in the database.
Info: different from the other monads, which have a
Flattenmethod,Choicedoesn’t. Does it meansChoiceisn’t a monad? Far from it! Here theFlattenmethod is replaced by an implict operator to allow accessing the inner value as so asFlattenwould do.
Here the list of available Choice types:
Choice<T1, T2>
Choice<T1, T2, T3>
Choice<T1, T2, T3, T4>
Choice<T1, T2, T3, T4, T5>